mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
Success dialog and Failed dialog changes with VisitorPasswordDialog
This commit is contained in:
@ -1,96 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"accessUser": "Ali Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-08-01",
|
|
||||||
"endTime": "2023-08-02",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
}, {
|
|
||||||
"accessUser": "oamr Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-08-01",
|
|
||||||
"endTime": "2023-08-05",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
}, {
|
|
||||||
"accessUser": "John Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-08-01",
|
|
||||||
"endTime": "2023-08-10",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"accessUser": "John Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-08-01",
|
|
||||||
"endTime": "2023-10-10",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"accessUser": "John Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-03-01",
|
|
||||||
"endTime": "2023-05-10",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"accessUser": "John Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-07-01",
|
|
||||||
"endTime": "2023-08-10",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
}, {
|
|
||||||
"accessUser": "John Doe",
|
|
||||||
"accessType": "Admin",
|
|
||||||
"startTime": "2023-01-01",
|
|
||||||
"endTime": "2023-09-05",
|
|
||||||
"accessibleDevice": "Smart Door",
|
|
||||||
"authorizationSource": "System",
|
|
||||||
"authorizer": "Jane Smith",
|
|
||||||
"authorizationTime": "2023-08-01 10:00 AM",
|
|
||||||
"accessStatus": "Granted",
|
|
||||||
"actions": "View"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"accessUser": "Alice Johnson",
|
|
||||||
"accessType": "User",
|
|
||||||
"startTime": "2023-08-01",
|
|
||||||
"endTime": "2023-08-10",
|
|
||||||
"accessibleDevice": "Smart Lock",
|
|
||||||
"authorizationSource": "Admin",
|
|
||||||
"authorizer": "John Doe",
|
|
||||||
"authorizationTime": "2023-08-02 11:00 AM",
|
|
||||||
"accessStatus": "Pending",
|
|
||||||
"actions": "Approve"
|
|
||||||
}
|
|
||||||
]
|
|
@ -5,8 +5,7 @@ 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/auth/view/login_page.dart';
|
||||||
import 'package:syncrow_web/pages/home/bloc/home_bloc.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/home/view/home_page.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/view/add_device_dialog.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/services/locator.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
@ -30,6 +29,8 @@ class MyApp extends StatelessWidget {
|
|||||||
return MultiBlocProvider(
|
return MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(create: (context) => HomeBloc()),
|
BlocProvider(create: (context) => HomeBloc()),
|
||||||
|
BlocProvider<VisitorPasswordBloc>(
|
||||||
|
create: (context) => VisitorPasswordBloc(),)
|
||||||
],
|
],
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
debugShowCheckedModeBanner: false, // Hide debug banner
|
debugShowCheckedModeBanner: false, // Hide debug banner
|
||||||
|
@ -39,12 +39,9 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void updateTabsCount() {
|
void updateTabsCount() {
|
||||||
// Count occurrences based on the type field
|
|
||||||
int toBeEffectiveCount = data.where((item) => item.passwordStatus.value== 'To Be Effective').length;
|
int toBeEffectiveCount = data.where((item) => item.passwordStatus.value== 'To Be Effective').length;
|
||||||
int effectiveCount = data.where((item) => item.passwordStatus.value == 'Effective').length;
|
int effectiveCount = data.where((item) => item.passwordStatus.value == 'Effective').length;
|
||||||
int expiredCount = data.where((item) => item.passwordStatus.value == 'Expired').length;
|
int expiredCount = data.where((item) => item.passwordStatus.value == 'Expired').length;
|
||||||
|
|
||||||
// Update tab labels with counts
|
|
||||||
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)';
|
||||||
@ -53,7 +50,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
|
|
||||||
|
|
||||||
int selectedIndex = 0;
|
int selectedIndex = 0;
|
||||||
|
|
||||||
final List<String> tabs = [
|
final List<String> tabs = [
|
||||||
'All',
|
'All',
|
||||||
'To Be Effective (0)',
|
'To Be Effective (0)',
|
||||||
@ -76,7 +72,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
|
|
||||||
|
|
||||||
Future<void> selectTime(SelectTime event, Emitter<AccessState> emit) async {
|
Future<void> selectTime(SelectTime event, Emitter<AccessState> emit) async {
|
||||||
|
|
||||||
final DateTime? picked = await showDatePicker(
|
final DateTime? picked = await showDatePicker(
|
||||||
context: event.context,
|
context: event.context,
|
||||||
initialDate: DateTime.now(),
|
initialDate: DateTime.now(),
|
||||||
@ -146,8 +141,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
try {
|
try {
|
||||||
filteredData = data.where((item) {
|
filteredData = data.where((item) {
|
||||||
bool matchesCriteria = true;
|
bool matchesCriteria = true;
|
||||||
|
|
||||||
// Filter by password name if provided
|
|
||||||
if (event.passwordName != null && event.passwordName!.isNotEmpty) {
|
if (event.passwordName != null && event.passwordName!.isNotEmpty) {
|
||||||
final bool matchesName = item.passwordName != null &&
|
final bool matchesName = item.passwordName != null &&
|
||||||
item.passwordName.contains(event.passwordName);
|
item.passwordName.contains(event.passwordName);
|
||||||
@ -155,8 +148,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
matchesCriteria = false;
|
matchesCriteria = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter by date range if provided
|
|
||||||
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());
|
||||||
@ -170,8 +161,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter by tab selection
|
|
||||||
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') {
|
||||||
@ -179,7 +168,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
} 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;
|
||||||
}).toList();
|
}).toList();
|
||||||
emit(TableLoaded(filteredData));
|
emit(TableLoaded(filteredData));
|
||||||
@ -206,7 +194,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
try {
|
try {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
selectedIndex = event.selectedIndex;
|
selectedIndex = event.selectedIndex;
|
||||||
// Apply filtering based on selected tab
|
|
||||||
switch (selectedIndex) {
|
switch (selectedIndex) {
|
||||||
case 0: // All
|
case 0: // All
|
||||||
filteredData = data;
|
filteredData = data;
|
||||||
@ -216,7 +203,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
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();
|
||||||
@ -225,7 +211,7 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
filteredData = data;
|
filteredData = data;
|
||||||
}
|
}
|
||||||
add(FilterDataEvent(
|
add(FilterDataEvent(
|
||||||
selectedTabIndex: selectedIndex, // Pass the selected tab index
|
selectedTabIndex: selectedIndex,
|
||||||
passwordName: passwordName.text.toLowerCase(),
|
passwordName: passwordName.text.toLowerCase(),
|
||||||
startTime: effectiveTimeTimeStamp,
|
startTime: effectiveTimeTimeStamp,
|
||||||
endTime: expirationTimeTimeStamp
|
endTime: expirationTimeTimeStamp
|
||||||
|
@ -21,17 +21,14 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
enableMenuSideba: false,
|
enableMenuSideba: false,
|
||||||
appBarTitle: Row(
|
appBarTitle: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text('Access Management',
|
||||||
'Access Management',
|
|
||||||
style: Theme.of(context).textTheme.headlineLarge,
|
style: Theme.of(context).textTheme.headlineLarge,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
appBarBody: [
|
appBarBody: [
|
||||||
Text(
|
Text('Physical Access',
|
||||||
'Physical Access',
|
style: Theme.of(context).textTheme
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.headlineMedium!
|
.headlineMedium!
|
||||||
.copyWith(color: Colors.white),
|
.copyWith(color: Colors.white),
|
||||||
),
|
),
|
||||||
@ -101,7 +98,9 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
textBaseline: TextBaseline.ideographic, children: [
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@ -111,7 +110,7 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
color: Colors.black,fontSize: 13),),
|
color: Colors.black,fontSize: 13),),
|
||||||
const SizedBox(height: 5,),
|
const SizedBox(height: 5,),
|
||||||
Container(
|
Container(
|
||||||
height:size.height * 0.053,
|
height:43,
|
||||||
width: size.width * 0.15,
|
width: size.width * 0.15,
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
@ -145,51 +144,44 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
|
height:45,
|
||||||
|
|
||||||
width: size.width * 0.06,
|
width: size.width * 0.06,
|
||||||
child: Column(
|
child:Container(
|
||||||
children: [
|
decoration: containerDecoration,
|
||||||
Text(''),
|
child: DefaultButton(
|
||||||
Container(
|
onPressed: () {
|
||||||
decoration: containerDecoration,
|
accessBloc.add(FilterDataEvent(
|
||||||
child: DefaultButton(
|
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex, // Pass the selected tab index
|
||||||
onPressed: () {
|
passwordName: accessBloc.passwordName.text.toLowerCase(),
|
||||||
accessBloc.add(FilterDataEvent(
|
startTime: accessBloc.effectiveTimeTimeStamp,
|
||||||
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex, // Pass the selected tab index
|
endTime: accessBloc.expirationTimeTimeStamp
|
||||||
passwordName: accessBloc.passwordName.text.toLowerCase(),
|
));
|
||||||
startTime: accessBloc.effectiveTimeTimeStamp,
|
}, borderRadius: 9,
|
||||||
endTime: accessBloc.expirationTimeTimeStamp
|
child: const Text('Search'))),
|
||||||
));
|
|
||||||
}, borderRadius: 9,
|
|
||||||
child: const Text('Search'))),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 10,
|
width: 10,
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
|
height:45,
|
||||||
width: size.width * 0.06,
|
width: size.width * 0.06,
|
||||||
child: Column(
|
child: Container(
|
||||||
children: [
|
decoration: containerDecoration,
|
||||||
Text(''),
|
child: DefaultButton(
|
||||||
Container(
|
onPressed: () {
|
||||||
decoration: containerDecoration,
|
accessBloc.add(ResetSearch());
|
||||||
child: DefaultButton(
|
},
|
||||||
onPressed: () {
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
accessBloc.add(ResetSearch());
|
borderRadius: 9,
|
||||||
},
|
child: Text(
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
'Reset',
|
||||||
borderRadius: 9,
|
style: Theme.of(context)
|
||||||
child: Text(
|
.textTheme
|
||||||
'Reset',
|
.bodySmall!
|
||||||
style: Theme.of(context)
|
.copyWith(color: Colors.black),
|
||||||
.textTheme
|
|
||||||
.bodySmall!
|
|
||||||
.copyWith(color: Colors.black),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -146,7 +146,6 @@ class LoginMobilePage extends StatelessWidget {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
isDense: true,
|
isDense: true,
|
||||||
style: const TextStyle(color: Colors.black),
|
style: const TextStyle(color: Colors.black),
|
||||||
items:loginBloc.regionList!.map((RegionModel region) {
|
items:loginBloc.regionList!.map((RegionModel region) {
|
||||||
@ -156,7 +155,6 @@ class LoginMobilePage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
print(value);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
75
lib/pages/common/custom_dialog.dart
Normal file
75
lib/pages/common/custom_dialog.dart
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
|
Future<void> showCustomDialog({
|
||||||
|
required BuildContext context,
|
||||||
|
required String message,
|
||||||
|
String? title,
|
||||||
|
String? iconPath,
|
||||||
|
double? dialogHeight,
|
||||||
|
double? iconHeight,
|
||||||
|
double? iconWidth,
|
||||||
|
VoidCallback? onOkPressed,
|
||||||
|
bool barrierDismissible = false, required actions,
|
||||||
|
}) {
|
||||||
|
return showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: barrierDismissible,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
final size = MediaQuery.of(context).size;
|
||||||
|
return AlertDialog(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
content: SizedBox(
|
||||||
|
height: dialogHeight ?? size.height * 0.15,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
if (iconPath != null)
|
||||||
|
SvgPicture.asset(
|
||||||
|
iconPath,
|
||||||
|
height: iconHeight ?? 35,
|
||||||
|
width: iconWidth ?? 35,
|
||||||
|
),
|
||||||
|
if (title != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Colors.black),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(
|
||||||
|
message,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium!
|
||||||
|
.copyWith(color: Colors.black),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actionsAlignment: MainAxisAlignment.center,
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: onOkPressed ?? () => Navigator.of(context).pop(),
|
||||||
|
child: Text(
|
||||||
|
'OK',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
fontSize: 16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
@ -15,7 +15,7 @@ class DynamicTable extends StatefulWidget {
|
|||||||
final void Function(int, bool?)? onRowCheckboxChanged;
|
final void Function(int, bool?)? onRowCheckboxChanged;
|
||||||
|
|
||||||
const DynamicTable({
|
const DynamicTable({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.headers,
|
required this.headers,
|
||||||
required this.data,
|
required this.data,
|
||||||
required this.size,
|
required this.size,
|
||||||
@ -25,7 +25,7 @@ class DynamicTable extends StatefulWidget {
|
|||||||
this.cellDecoration,
|
this.cellDecoration,
|
||||||
this.selectAll,
|
this.selectAll,
|
||||||
this.onRowCheckboxChanged,
|
this.onRowCheckboxChanged,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_DynamicTableState createState() => _DynamicTableState();
|
_DynamicTableState createState() => _DynamicTableState();
|
||||||
@ -66,7 +66,7 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
return Container(
|
return Container(
|
||||||
decoration: widget.cellDecoration,
|
decoration: widget.cellDecoration,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(2.0),
|
||||||
child:
|
child:
|
||||||
ListView(
|
ListView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
@ -102,7 +102,7 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
SvgPicture.asset(
|
SvgPicture.asset(
|
||||||
Assets.emptyTable
|
Assets.emptyTable
|
||||||
),
|
),
|
||||||
SizedBox(height: 15,),
|
const SizedBox(height: 15,),
|
||||||
Text('No Passwords',style: Theme.of(context).textTheme.bodySmall!.copyWith(color:ColorsManager.grayColor ),)
|
Text('No Passwords',style: Theme.of(context).textTheme.bodySmall!.copyWith(color:ColorsManager.grayColor ),)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -122,9 +122,9 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
if (widget.withCheckBox)
|
if (widget.withCheckBox)
|
||||||
_buildRowCheckbox(index),
|
_buildRowCheckbox(index,widget.size.height*0.10),
|
||||||
...row.map((cell) =>
|
...row.map((cell) =>
|
||||||
_buildTableCell(cell.toString())).toList(),
|
_buildTableCell(cell.toString(),widget.size.height*0.10)).toList(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -141,8 +141,12 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSelectAllCheckbox() {
|
Widget _buildSelectAllCheckbox() {
|
||||||
return SizedBox(
|
return Container(
|
||||||
width: 50,
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border.symmetric(
|
||||||
|
vertical: BorderSide(color: ColorsManager.boxDivider))),
|
||||||
child: Checkbox(
|
child: Checkbox(
|
||||||
value: _selectAll,
|
value: _selectAll,
|
||||||
onChanged: _toggleSelectAll,
|
onChanged: _toggleSelectAll,
|
||||||
@ -150,16 +154,27 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildRowCheckbox(int index) {
|
Widget _buildRowCheckbox(int index,size) {
|
||||||
return SizedBox(
|
return Container(
|
||||||
width: 50,
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Checkbox(
|
|
||||||
|
height:size ,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: ColorsManager.boxDivider,
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Center(child: Checkbox(
|
||||||
value: _selected[index],
|
value: _selected[index],
|
||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
_toggleRowSelection(index, value);
|
_toggleRowSelection(index, value);
|
||||||
},
|
},
|
||||||
),
|
),)
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTableHeaderCell(String title) {
|
Widget _buildTableHeaderCell(String title) {
|
||||||
@ -177,11 +192,11 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTableCell(String content) {
|
Widget _buildTableCell(String content,size) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 80,
|
height:size ,
|
||||||
padding: const EdgeInsets.all(15.0),
|
padding: const EdgeInsets.all(5.0),
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
bottom: BorderSide(
|
bottom: BorderSide(
|
||||||
|
@ -33,8 +33,7 @@ class CustomWebTextField extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text('* ',
|
Text('* ',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme.bodyMedium!
|
||||||
.bodyMedium!
|
|
||||||
.copyWith(color: Colors.red),
|
.copyWith(color: Colors.red),
|
||||||
),
|
),
|
||||||
Text(textFieldName, style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
Text(textFieldName, style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
@ -46,10 +45,8 @@ class CustomWebTextField extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
description??'',
|
description??'',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme.bodySmall!
|
||||||
.bodySmall!
|
.copyWith(fontSize: 9,
|
||||||
.copyWith(
|
|
||||||
fontSize: 9,
|
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: ColorsManager.textGray),
|
color: ColorsManager.textGray),
|
||||||
),
|
),
|
||||||
@ -65,21 +62,19 @@ class CustomWebTextField extends StatelessWidget {
|
|||||||
color: Colors.grey.withOpacity(0.3),
|
color: Colors.grey.withOpacity(0.3),
|
||||||
spreadRadius:2,
|
spreadRadius:2,
|
||||||
blurRadius: 3,
|
blurRadius: 3,
|
||||||
offset: Offset(1, 1), // changes position of shadow
|
offset: const Offset(1, 1), // changes position of shadow
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
child: Container(
|
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: const TextStyle(height: 0), // Hide the error text space
|
||||||
errorStyle: const TextStyle(height: 0), // Hide the error text space
|
|
||||||
|
|
||||||
hintText: 'Please enter'),
|
hintText: 'Please enter'),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
class HourPickerDialog extends StatefulWidget {
|
class HourPickerDialog extends StatefulWidget {
|
||||||
final TimeOfDay initialTime;
|
final TimeOfDay initialTime;
|
||||||
HourPickerDialog({required this.initialTime});
|
const HourPickerDialog({super.key, required this.initialTime});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_HourPickerDialogState createState() => _HourPickerDialogState();
|
_HourPickerDialogState createState() => _HourPickerDialogState();
|
||||||
@ -24,7 +24,7 @@ class _HourPickerDialogState extends State<HourPickerDialog> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: Text('Select Hour'),
|
title: const Text('Select Hour'),
|
||||||
content: Row(
|
content: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
@ -46,7 +46,7 @@ class _HourPickerDialogState extends State<HourPickerDialog> {
|
|||||||
SizedBox(width: 16.0),
|
SizedBox(width: 16.0),
|
||||||
DropdownButton<bool>(
|
DropdownButton<bool>(
|
||||||
value: _isPm,
|
value: _isPm,
|
||||||
items: [
|
items: const [
|
||||||
DropdownMenuItem(
|
DropdownMenuItem(
|
||||||
value: false,
|
value: false,
|
||||||
child: Text('AM'),
|
child: Text('AM'),
|
||||||
@ -67,14 +67,14 @@ class _HourPickerDialogState extends State<HourPickerDialog> {
|
|||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(null),
|
onPressed: () => Navigator.of(context).pop(null),
|
||||||
child: Text('Cancel'),
|
child: const Text('Cancel'),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
int hour = _isPm ? _selectedHour + 12 : _selectedHour;
|
int hour = _isPm ? _selectedHour + 12 : _selectedHour;
|
||||||
Navigator.of(context).pop(TimeOfDay(hour: hour, minute: 0));
|
Navigator.of(context).pop(TimeOfDay(hour: hour, minute: 0));
|
||||||
},
|
},
|
||||||
child: Text('OK'),
|
child: const Text('OK'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -66,7 +66,7 @@ class InfoDialog extends StatelessWidget {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
child: Text('OK'),
|
child: const Text('OK'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -2,13 +2,11 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/home/bloc/home_state.dart';
|
||||||
import 'package:syncrow_web/pages/home/view/home_card.dart';
|
import 'package:syncrow_web/pages/home/view/home_card.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
||||||
|
|
||||||
import '../bloc/home_state.dart';
|
|
||||||
|
|
||||||
class HomeWebPage extends StatelessWidget {
|
class HomeWebPage extends StatelessWidget {
|
||||||
HomeWebPage({super.key});
|
HomeWebPage({super.key});
|
||||||
@override
|
@override
|
||||||
|
@ -2,6 +2,7 @@ import 'dart:math';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/custom_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/common/hour_picker_dialog.dart';
|
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_event.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||||
@ -9,9 +10,9 @@ import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
|||||||
import 'package:syncrow_web/pages/visitor_password/model/schedule_model.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/services/access_mang_api.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||||
|
|
||||||
|
|
||||||
class VisitorPasswordBloc
|
class VisitorPasswordBloc
|
||||||
extends Bloc<VisitorPasswordEvent, VisitorPasswordState> {
|
extends Bloc<VisitorPasswordEvent, VisitorPasswordState> {
|
||||||
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
|
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
|
||||||
@ -23,10 +24,8 @@ class VisitorPasswordBloc
|
|||||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||||
on<SelectDeviceEvent>(selectDevice);
|
on<SelectDeviceEvent>(selectDevice);
|
||||||
on<UpdateFilteredDevicesEvent>(_onUpdateFilteredDevices);
|
on<UpdateFilteredDevicesEvent>(_onUpdateFilteredDevices);
|
||||||
|
|
||||||
on<OnlineOneTimePasswordEvent>(postOnlineOneTimePassword);
|
on<OnlineOneTimePasswordEvent>(postOnlineOneTimePassword);
|
||||||
on<OnlineMultipleTimePasswordEvent>(postOnlineMultipleTimePassword);
|
on<OnlineMultipleTimePasswordEvent>(postOnlineMultipleTimePassword);
|
||||||
|
|
||||||
on<OfflineMultipleTimePasswordEvent>(postOfflineMultipleTimePassword);
|
on<OfflineMultipleTimePasswordEvent>(postOfflineMultipleTimePassword);
|
||||||
on<OfflineOneTimePasswordEvent>(postOfflineOneTimePassword);
|
on<OfflineOneTimePasswordEvent>(postOfflineOneTimePassword);
|
||||||
on<SelectTimeEvent>(selectTimeOfLinePassword);
|
on<SelectTimeEvent>(selectTimeOfLinePassword);
|
||||||
@ -58,16 +57,12 @@ class VisitorPasswordBloc
|
|||||||
int? effectiveTimeTimeStamp;
|
int? effectiveTimeTimeStamp;
|
||||||
int? expirationTimeTimeStamp;
|
int? expirationTimeTimeStamp;
|
||||||
|
|
||||||
int? repeatEffectiveTimeTimeStamp;
|
|
||||||
int? repeatExpirationTimeTimeStamp;
|
|
||||||
|
|
||||||
DateTime? startTime = DateTime.now();
|
DateTime? startTime = DateTime.now();
|
||||||
DateTime? endTime;
|
DateTime? endTime;
|
||||||
|
|
||||||
String startTimeAccess = 'Start Time';
|
String startTimeAccess = 'Start Time';
|
||||||
String endTimeAccess = 'End Time';
|
String endTimeAccess = 'End Time';
|
||||||
|
|
||||||
|
|
||||||
selectAccessType(
|
selectAccessType(
|
||||||
SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
|
SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
|
||||||
accessTypeSelected = event.type;
|
accessTypeSelected = event.type;
|
||||||
@ -81,9 +76,9 @@ class VisitorPasswordBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> selectTimeVisitorPassword(
|
Future<void> selectTimeVisitorPassword(
|
||||||
SelectTimeVisitorPassword event,
|
SelectTimeVisitorPassword event,
|
||||||
Emitter<VisitorPasswordState> emit,
|
Emitter<VisitorPasswordState> emit,
|
||||||
) async {
|
) async {
|
||||||
final DateTime? picked = await showDatePicker(
|
final DateTime? picked = await showDatePicker(
|
||||||
context: event.context,
|
context: event.context,
|
||||||
initialDate: DateTime.now(),
|
initialDate: DateTime.now(),
|
||||||
@ -122,7 +117,8 @@ class VisitorPasswordBloc
|
|||||||
timePicked.minute,
|
timePicked.minute,
|
||||||
);
|
);
|
||||||
|
|
||||||
final selectedTimestamp = selectedDateTime.millisecondsSinceEpoch ~/ 1000;
|
final selectedTimestamp =
|
||||||
|
selectedDateTime.millisecondsSinceEpoch ~/ 1000;
|
||||||
|
|
||||||
if (event.isStart) {
|
if (event.isStart) {
|
||||||
if (expirationTimeTimeStamp != null &&
|
if (expirationTimeTimeStamp != null &&
|
||||||
@ -133,9 +129,7 @@ class VisitorPasswordBloc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
effectiveTimeTimeStamp = selectedTimestamp;
|
effectiveTimeTimeStamp = selectedTimestamp;
|
||||||
|
startTimeAccess = selectedDateTime.toString().split('.').first;
|
||||||
startTimeAccess = selectedDateTime.toString().split('.').first;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (effectiveTimeTimeStamp != null &&
|
if (effectiveTimeTimeStamp != null &&
|
||||||
selectedTimestamp < effectiveTimeTimeStamp!) {
|
selectedTimestamp < effectiveTimeTimeStamp!) {
|
||||||
@ -145,11 +139,8 @@ class VisitorPasswordBloc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
expirationTimeTimeStamp = selectedTimestamp;
|
expirationTimeTimeStamp = selectedTimestamp;
|
||||||
|
endTimeAccess = selectedDateTime.toString().split('.').first;
|
||||||
endTimeAccess = selectedDateTime.toString().split('.').first;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(ChangeTimeState());
|
emit(ChangeTimeState());
|
||||||
emit(VisitorPasswordInitial());
|
emit(VisitorPasswordInitial());
|
||||||
}
|
}
|
||||||
@ -201,10 +192,10 @@ class VisitorPasswordBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
//online password
|
//online password
|
||||||
|
|
||||||
Future<void> postOnlineOneTimePassword(OnlineOneTimePasswordEvent event,
|
Future<void> postOnlineOneTimePassword(OnlineOneTimePasswordEvent event,
|
||||||
Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
generate7DigitNumber();
|
generate7DigitNumber();
|
||||||
bool res = await AccessMangApi().postOnlineOneTime(
|
bool res = await AccessMangApi().postOnlineOneTime(
|
||||||
email: event.email,
|
email: event.email,
|
||||||
@ -213,27 +204,37 @@ class VisitorPasswordBloc
|
|||||||
passwordName: event.passwordName,
|
passwordName: event.passwordName,
|
||||||
effectiveTime: effectiveTimeTimeStamp.toString(),
|
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||||
invalidTime: expirationTimeTimeStamp.toString());
|
invalidTime: expirationTimeTimeStamp.toString());
|
||||||
if (res = true) {
|
if (res == true) {
|
||||||
Navigator.pop(event.context!);
|
emit(SuccessState());
|
||||||
|
} else {
|
||||||
|
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!);
|
||||||
|
stateDialog(
|
||||||
|
context: event.context!,
|
||||||
|
message: e.toString(),
|
||||||
|
title: 'Something Wrong');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> postOnlineMultipleTimePassword(
|
Future<void> postOnlineMultipleTimePassword(
|
||||||
OnlineMultipleTimePasswordEvent event,
|
OnlineMultipleTimePasswordEvent event,
|
||||||
Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
generate7DigitNumber();
|
emit(LoadingInitialState());
|
||||||
bool res = await AccessMangApi().postOnlineMultipleTime(
|
|
||||||
|
await generate7DigitNumber();
|
||||||
|
bool res = await AccessMangApi().postOnlineMultipleTime(
|
||||||
scheduleList: [
|
scheduleList: [
|
||||||
if (repeat)
|
if (repeat)
|
||||||
Schedule(
|
Schedule(
|
||||||
effectiveTime: getTimeFromDateTimeString(expirationTime),
|
effectiveTime: getTimeFromDateTimeString(expirationTime),
|
||||||
invalidTime: getTimeFromDateTimeString(effectiveTime).toString(),
|
invalidTime:
|
||||||
|
getTimeFromDateTimeString(effectiveTime).toString(),
|
||||||
workingDay: selectedDays,
|
workingDay: selectedDays,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -243,9 +244,11 @@ class VisitorPasswordBloc
|
|||||||
email: event.email,
|
email: event.email,
|
||||||
devicesUuid: selectedDevices,
|
devicesUuid: selectedDevices,
|
||||||
passwordName: event.passwordName);
|
passwordName: event.passwordName);
|
||||||
if(res==true){
|
if (res == true) {
|
||||||
Navigator.pop(event.context!);
|
emit(SuccessState());
|
||||||
|
emit(TableLoaded(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
}
|
}
|
||||||
@ -255,11 +258,16 @@ class VisitorPasswordBloc
|
|||||||
Future<void> postOfflineOneTimePassword(OfflineOneTimePasswordEvent event,
|
Future<void> postOfflineOneTimePassword(OfflineOneTimePasswordEvent event,
|
||||||
Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
generate7DigitNumber();
|
emit(LoadingInitialState());
|
||||||
await AccessMangApi().postOffLineOneTime(
|
await generate7DigitNumber();
|
||||||
|
bool res = await AccessMangApi().postOffLineOneTime(
|
||||||
email: event.email,
|
email: event.email,
|
||||||
devicesUuid: selectedDevices,
|
devicesUuid: selectedDevices,
|
||||||
passwordName: event.passwordName);
|
passwordName: event.passwordName);
|
||||||
|
if (res == true) {
|
||||||
|
emit(SuccessState());
|
||||||
|
emit(TableLoaded(data));
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
}
|
}
|
||||||
@ -269,15 +277,19 @@ class VisitorPasswordBloc
|
|||||||
OfflineMultipleTimePasswordEvent event,
|
OfflineMultipleTimePasswordEvent event,
|
||||||
Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
generate7DigitNumber();
|
emit(LoadingInitialState());
|
||||||
await AccessMangApi().postOffLineMultipleTime(
|
await generate7DigitNumber();
|
||||||
email: event.email,
|
bool res = await AccessMangApi().postOffLineMultipleTime(
|
||||||
devicesUuid: selectedDevices,
|
email: event.email,
|
||||||
passwordName: event.passwordName,
|
devicesUuid: selectedDevices,
|
||||||
|
passwordName: event.passwordName,
|
||||||
invalidTime: expirationTimeTimeStamp.toString(),
|
invalidTime: expirationTimeTimeStamp.toString(),
|
||||||
effectiveTime: effectiveTimeTimeStamp.toString(),
|
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||||
|
|
||||||
);
|
);
|
||||||
|
if (res == true) {
|
||||||
|
emit(SuccessState());
|
||||||
|
emit(TableLoaded(data));
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
}
|
}
|
||||||
@ -300,13 +312,11 @@ class VisitorPasswordBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future generate7DigitNumber() async {
|
Future generate7DigitNumber() async {
|
||||||
emit(LoadingInitialState());
|
|
||||||
passwordController = '';
|
passwordController = '';
|
||||||
Random random = Random();
|
Random random = Random();
|
||||||
int min = 1000000;
|
int min = 1000000;
|
||||||
int max = 9999999;
|
int max = 9999999;
|
||||||
passwordController = (min + random.nextInt(max - min + 1)).toString();
|
passwordController = (min + random.nextInt(max - min + 1)).toString();
|
||||||
emit(GeneratePasswordState());
|
|
||||||
return passwordController;
|
return passwordController;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,12 +329,10 @@ class VisitorPasswordBloc
|
|||||||
final deviceName = deviceNameController.text.toLowerCase();
|
final deviceName = deviceNameController.text.toLowerCase();
|
||||||
final deviceId = deviceIdController.text.toLowerCase();
|
final deviceId = deviceIdController.text.toLowerCase();
|
||||||
final unitName = unitNameController.text.toLowerCase();
|
final unitName = unitNameController.text.toLowerCase();
|
||||||
|
|
||||||
final filteredData = data.where((device) {
|
final filteredData = data.where((device) {
|
||||||
final matchesDeviceName = device.name.toLowerCase().contains(deviceName);
|
final matchesDeviceName = device.name.toLowerCase().contains(deviceName);
|
||||||
final matchesDeviceId = device.uuid.toLowerCase().contains(deviceId);
|
final matchesDeviceId = device.uuid.toLowerCase().contains(deviceId);
|
||||||
// final matchesUnitName = device.unitName.toLowerCase().contains(unitName); // Assuming unitName is a property of the device
|
// final matchesUnitName = device.unitName.toLowerCase().contains(unitName); // Assuming unitName is a property of the device
|
||||||
|
|
||||||
return matchesDeviceName && matchesDeviceId;
|
return matchesDeviceName && matchesDeviceId;
|
||||||
}).toList();
|
}).toList();
|
||||||
add(UpdateFilteredDevicesEvent(filteredData));
|
add(UpdateFilteredDevicesEvent(filteredData));
|
||||||
@ -334,7 +342,6 @@ class VisitorPasswordBloc
|
|||||||
Stream<VisitorPasswordState> mapEventToState(
|
Stream<VisitorPasswordState> mapEventToState(
|
||||||
VisitorPasswordEvent event) async* {
|
VisitorPasswordEvent event) async* {
|
||||||
if (event is FetchDevice) {
|
if (event is FetchDevice) {
|
||||||
// Fetching logic...
|
|
||||||
} else if (event is UpdateFilteredDevicesEvent) {
|
} else if (event is UpdateFilteredDevicesEvent) {
|
||||||
yield TableLoaded(event.filteredData);
|
yield TableLoaded(event.filteredData);
|
||||||
}
|
}
|
||||||
@ -347,10 +354,11 @@ class VisitorPasswordBloc
|
|||||||
|
|
||||||
addDeviceToList(context) {
|
addDeviceToList(context) {
|
||||||
selectedDevices = selectedDeviceIds;
|
selectedDevices = selectedDeviceIds;
|
||||||
Navigator.of(context).pop(selectedDevices); // Close the dialog
|
Navigator.of(context).pop(selectedDevices);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> selectTimeOfLinePassword(SelectTimeEvent event, Emitter<VisitorPasswordState> emit) async {
|
Future<void> selectTimeOfLinePassword(
|
||||||
|
SelectTimeEvent event, Emitter<VisitorPasswordState> emit) async {
|
||||||
emit(ChangeTimeState());
|
emit(ChangeTimeState());
|
||||||
final DateTime? picked = await showDatePicker(
|
final DateTime? picked = await showDatePicker(
|
||||||
context: event.context,
|
context: event.context,
|
||||||
@ -416,11 +424,10 @@ class VisitorPasswordBloc
|
|||||||
endTime = event.val;
|
endTime = event.val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime? convertStringToDateTime(String dateTimeString) {
|
DateTime? convertStringToDateTime(String dateTimeString) {
|
||||||
try {
|
try {
|
||||||
// Define the input format. Adjust this pattern based on your input string format.
|
|
||||||
final DateFormat inputFormat = DateFormat('yyyy-MM-dd HH:mm:ss');
|
final DateFormat inputFormat = DateFormat('yyyy-MM-dd HH:mm:ss');
|
||||||
// Convert the string to a DateTime object.
|
|
||||||
DateTime dateTime = inputFormat.parse(dateTimeString);
|
DateTime dateTime = inputFormat.parse(dateTimeString);
|
||||||
return dateTime;
|
return dateTime;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -432,8 +439,6 @@ class VisitorPasswordBloc
|
|||||||
String getTimeFromDateTimeString(String dateTimeString) {
|
String getTimeFromDateTimeString(String dateTimeString) {
|
||||||
DateTime? dateTime = convertStringToDateTime(dateTimeString);
|
DateTime? dateTime = convertStringToDateTime(dateTimeString);
|
||||||
if (dateTime == null) return '';
|
if (dateTime == null) return '';
|
||||||
|
|
||||||
// Extract the time component from the DateTime object.
|
|
||||||
return DateFormat('HH:mm').format(dateTime);
|
return DateFormat('HH:mm').format(dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,4 +449,27 @@ class VisitorPasswordBloc
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> stateDialog({
|
||||||
|
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'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,11 +77,12 @@ class OnlineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
|||||||
|
|
||||||
//offline password
|
//offline password
|
||||||
class OfflineOneTimePasswordEvent extends VisitorPasswordEvent {
|
class OfflineOneTimePasswordEvent extends VisitorPasswordEvent {
|
||||||
|
final BuildContext? context;
|
||||||
final String? email;
|
final String? email;
|
||||||
final String? passwordName;
|
final String? passwordName;
|
||||||
const OfflineOneTimePasswordEvent({this.email,this.passwordName});
|
const OfflineOneTimePasswordEvent({this.email,this.passwordName,this.context});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [email!,passwordName!,];
|
List<Object> get props => [email!,passwordName!,context!,];
|
||||||
}
|
}
|
||||||
|
|
||||||
class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
||||||
@ -89,11 +90,12 @@ class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
|||||||
final String? passwordName;
|
final String? passwordName;
|
||||||
final String? invalidTime;
|
final String? invalidTime;
|
||||||
final String? effectiveTime;
|
final String? effectiveTime;
|
||||||
|
final BuildContext? context;
|
||||||
|
|
||||||
const OfflineMultipleTimePasswordEvent({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!];
|
List<Object> get props => [email!,passwordName!,invalidTime!,effectiveTime!,context!];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ 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 GeneratePasswordState extends VisitorPasswordState {}
|
class SuccessState extends VisitorPasswordState {}
|
||||||
|
|
||||||
class FailedState extends VisitorPasswordState {
|
class FailedState extends VisitorPasswordState {
|
||||||
final String message;
|
final String message;
|
||||||
|
@ -12,7 +12,6 @@ import 'package:syncrow_web/utils/constants/assets.dart';
|
|||||||
import 'package:syncrow_web/utils/constants/const.dart';
|
import 'package:syncrow_web/utils/constants/const.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
|
|
||||||
class AddDeviceDialog extends StatelessWidget {
|
class AddDeviceDialog extends StatelessWidget {
|
||||||
const AddDeviceDialog({super.key});
|
const AddDeviceDialog({super.key});
|
||||||
@override
|
@override
|
||||||
@ -54,7 +53,7 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
width: 15,
|
width: 15,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 10,),
|
const SizedBox(width: 10,),
|
||||||
Text('Only online accessible devices can be added',
|
Text('Only online accessible devices can be added',
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
@ -63,13 +62,15 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
SizedBox(height: 20,),
|
const SizedBox(height: 20,),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
textBaseline: TextBaseline.alphabetic,
|
||||||
|
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 4,
|
||||||
child: CustomWebTextField(
|
child: CustomWebTextField(
|
||||||
controller: visitorBloc.deviceNameController,
|
controller: visitorBloc.deviceNameController,
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
@ -79,7 +80,7 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 4,
|
||||||
child: CustomWebTextField(
|
child: CustomWebTextField(
|
||||||
controller: visitorBloc.deviceIdController,
|
controller: visitorBloc.deviceIdController,
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
@ -89,7 +90,7 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 4,
|
||||||
child: CustomWebTextField(
|
child: CustomWebTextField(
|
||||||
controller: visitorBloc.unitNameController,
|
controller: visitorBloc.unitNameController,
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
@ -97,67 +98,49 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
description: '',
|
description: '',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Column(
|
Expanded(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
flex: 2,
|
||||||
children: [
|
child: Container(
|
||||||
const SizedBox(height: 25),
|
child: SizedBox(
|
||||||
Center(
|
width: size.width * 0.06,
|
||||||
child: Container(
|
child: Center(
|
||||||
height: 43,
|
child: DefaultButton(
|
||||||
width: 100,
|
onPressed: () {
|
||||||
decoration: containerDecoration,
|
visitorBloc.filterDevices();
|
||||||
child: Center(
|
},
|
||||||
child: DefaultButton(
|
borderRadius: 9,
|
||||||
onPressed: () {
|
child: const Text('Search'),
|
||||||
visitorBloc.filterDevices(); // Call filter function
|
|
||||||
},
|
|
||||||
borderRadius: 9,
|
|
||||||
child: const Text('Search'),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Column(
|
Expanded(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
flex: 2,
|
||||||
children: [
|
child: Container(
|
||||||
const SizedBox(height: 25),
|
width: size.width * 0.06,
|
||||||
|
child: DefaultButton(
|
||||||
Center(
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
child: Container(
|
borderRadius: 9,
|
||||||
height: 43,
|
child: Text('Reset',
|
||||||
width: 100,
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),
|
||||||
decoration: containerDecoration,
|
|
||||||
child: Center(
|
|
||||||
child: DefaultButton(
|
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
|
||||||
borderRadius: 9,
|
|
||||||
child: Text(
|
|
||||||
'Reset',
|
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
visitorBloc.deviceNameController.clear();
|
|
||||||
visitorBloc.deviceIdController.clear();
|
|
||||||
visitorBloc.unitNameController.clear();
|
|
||||||
visitorBloc.add(FetchDevice()); // Reset to original list
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
onPressed: () {
|
||||||
|
visitorBloc.deviceNameController.clear();
|
||||||
|
visitorBloc.deviceIdController.clear();
|
||||||
|
visitorBloc.unitNameController.clear();
|
||||||
|
visitorBloc.add(FetchDevice()); // Reset to original list
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
)
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Expanded(
|
Expanded(
|
||||||
|
flex: 3,
|
||||||
child: state is TableLoaded
|
child: state is TableLoaded
|
||||||
? DynamicTable(
|
? DynamicTable(
|
||||||
cellDecoration: containerDecoration,
|
cellDecoration: containerDecoration,
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:syncrow_web/pages/common/custom_web_textfield.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/date_time_widget.dart';
|
||||||
import 'package:syncrow_web/pages/common/default_button.dart';
|
import 'package:syncrow_web/pages/common/default_button.dart';
|
||||||
import 'package:syncrow_web/pages/common/info_dialog.dart';
|
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_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_event.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||||
@ -21,441 +20,517 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
|
var text = Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
color: Colors.black,fontSize: 13);
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => VisitorPasswordBloc(),
|
create: (context) => VisitorPasswordBloc(),
|
||||||
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
child: BlocListener<VisitorPasswordBloc, VisitorPasswordState>(
|
||||||
builder: (BuildContext context, VisitorPasswordState state) {
|
listener: (context, state) {
|
||||||
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||||
bool isRepeat =
|
if (state is SuccessState) {
|
||||||
state is IsRepeatState ? state.repeat : visitorBloc.repeat;
|
visitorBloc.stateDialog(
|
||||||
return AlertDialog(
|
context: context,
|
||||||
backgroundColor: Colors.white,
|
message: 'Password Created Successfully',
|
||||||
title: Text(
|
title: 'Send Success',
|
||||||
'Create visitor password',
|
);
|
||||||
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
} else if (state is FailedState) {
|
||||||
fontWeight: FontWeight.w400,
|
visitorBloc.stateDialog(
|
||||||
fontSize: 24,
|
context: context,
|
||||||
color: Colors.black),
|
message: state.message,
|
||||||
),
|
title: 'Something Wrong',
|
||||||
content: SingleChildScrollView(
|
);
|
||||||
child: Form(
|
}
|
||||||
key: visitorBloc.forgetFormKey,
|
},
|
||||||
child: Padding(
|
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||||
padding: const EdgeInsets.all(5.0),
|
builder: (BuildContext context, VisitorPasswordState state) {
|
||||||
child: ListBody(
|
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||||
children: <Widget>[
|
bool isRepeat = state is IsRepeatState ? state.repeat : visitorBloc.repeat;
|
||||||
Container(
|
return AlertDialog(
|
||||||
child: Row(
|
backgroundColor: Colors.white,
|
||||||
children: [
|
title: Text(
|
||||||
Expanded(
|
'Create visitor password',
|
||||||
flex: 2,
|
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||||
child: CustomWebTextField(
|
fontWeight: FontWeight.w400,
|
||||||
validator: visitorBloc.validate,
|
fontSize: 24,
|
||||||
controller: visitorBloc.userNameController,
|
color: Colors.black),
|
||||||
isRequired: true,
|
),
|
||||||
textFieldName: 'Name',
|
content:
|
||||||
description: '',
|
state is LoadingInitialState ?const Center(child: CircularProgressIndicator()):
|
||||||
),
|
SingleChildScrollView(
|
||||||
),
|
child: Form(
|
||||||
const Spacer(),
|
key: visitorBloc.forgetFormKey,
|
||||||
Expanded(
|
child: Padding(
|
||||||
flex: 2,
|
padding: const EdgeInsets.all(5.0),
|
||||||
child: CustomWebTextField(
|
child: ListBody(
|
||||||
validator: visitorBloc.validateEmail,
|
children: <Widget>[
|
||||||
controller: visitorBloc.emailController,
|
Container(
|
||||||
isRequired: true,
|
child: Row(
|
||||||
textFieldName: 'Email Address',
|
|
||||||
description:
|
|
||||||
'The password will be sent to the visitor’s email address.',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Expanded(
|
||||||
'* ',
|
flex: 2,
|
||||||
style: Theme.of(context)
|
child: CustomWebTextField(
|
||||||
.textTheme
|
validator: visitorBloc.validate,
|
||||||
.bodyMedium!
|
controller: visitorBloc.userNameController,
|
||||||
.copyWith(color: Colors.red),
|
isRequired: true,
|
||||||
|
textFieldName: 'Name',
|
||||||
|
description: '',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Text('Access Type',
|
const Spacer(),
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
Expanded(
|
||||||
color: Colors.black,fontSize: 13),),
|
flex: 2,
|
||||||
|
child: CustomWebTextField(
|
||||||
|
validator: visitorBloc.validateEmail,
|
||||||
|
controller: visitorBloc.emailController,
|
||||||
|
isRequired: true,
|
||||||
|
textFieldName: 'Email Address',
|
||||||
|
description:
|
||||||
|
'The password will be sent to the visitor’s email address.',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
),
|
||||||
children: <Widget>[
|
const SizedBox(
|
||||||
SizedBox(
|
height: 15,
|
||||||
width: size.width * 0.15,
|
),
|
||||||
child: RadioListTile<String>(
|
Column(
|
||||||
title: Text('Online Password',
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
children: [
|
||||||
color: Colors.black,fontSize: 13),
|
Row(
|
||||||
),
|
|
||||||
value: 'Online Password',
|
|
||||||
groupValue: (state is PasswordTypeSelected)
|
|
||||||
? state.selectedType
|
|
||||||
: visitorBloc.accessTypeSelected,
|
|
||||||
onChanged: (String? value) {
|
|
||||||
if (value != null) {
|
|
||||||
print(value);
|
|
||||||
context
|
|
||||||
.read<VisitorPasswordBloc>()
|
|
||||||
.add(SelectPasswordType(value));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: size.width * 0.15,
|
|
||||||
child: RadioListTile<String>(
|
|
||||||
title: Text('Offline Password',
|
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
|
||||||
color: Colors.black,fontSize: 13),),
|
|
||||||
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.15,
|
|
||||||
child: RadioListTile<String>(
|
|
||||||
title: Text('Dynamic Password',
|
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
|
||||||
color: Colors.black,fontSize: 13),),
|
|
||||||
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 = '';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
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),),
|
|
||||||
const SizedBox(
|
|
||||||
height: 20,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
visitorBloc.accessTypeSelected == 'Dynamic Password'
|
|
||||||
? SizedBox()
|
|
||||||
: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Text(
|
||||||
children: [
|
'* ',
|
||||||
Text(
|
style: Theme.of(context).textTheme
|
||||||
'* ',
|
.bodyMedium!.copyWith(color: Colors.red),
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodyMedium!
|
|
||||||
.copyWith(color: Colors.red),
|
|
||||||
),
|
|
||||||
Text('Usage Frequency',style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
|
||||||
color: Colors.black,fontSize: 13),),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
Row(
|
Text('Access Type',
|
||||||
children: <Widget>[
|
style:text ),
|
||||||
SizedBox(
|
|
||||||
width: 200,
|
|
||||||
child: RadioListTile<String>(
|
|
||||||
title: Text('One-Time',
|
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
|
||||||
color: Colors.black,fontSize: 13),),
|
|
||||||
value: 'One-Time',
|
|
||||||
groupValue:
|
|
||||||
(state is UsageFrequencySelected)
|
|
||||||
? state.selectedFrequency
|
|
||||||
: visitorBloc.usageFrequencySelected,
|
|
||||||
onChanged: (String? value) {
|
|
||||||
if (value != null) {
|
|
||||||
context.read<VisitorPasswordBloc>()
|
|
||||||
.add(SelectUsageFrequency(value));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: 200,
|
|
||||||
child: RadioListTile<String>(
|
|
||||||
title: Text('Periodic',
|
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
|
||||||
color: Colors.black,fontSize: 13),),
|
|
||||||
value: 'Periodic',
|
|
||||||
groupValue: (state is UsageFrequencySelected)
|
|
||||||
? state.selectedFrequency
|
|
||||||
: visitorBloc.usageFrequencySelected,
|
|
||||||
onChanged: (String? value) {
|
|
||||||
if (value != null) {
|
|
||||||
context
|
|
||||||
.read<VisitorPasswordBloc>()
|
|
||||||
.add(SelectUsageFrequency(value));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Text('Within the validity period, each device can be unlocked only once.',
|
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
|
||||||
color: ColorsManager.grayColor,fontSize: 9),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
Row(
|
||||||
height: 20,
|
children: <Widget>[
|
||||||
),
|
SizedBox(
|
||||||
if ((visitorBloc.usageFrequencySelected != 'One-Time' ||
|
width: size.width * 0.15,
|
||||||
visitorBloc.accessTypeSelected != 'Offline Password') &&
|
child: RadioListTile<String>(
|
||||||
(visitorBloc.usageFrequencySelected != ''))
|
title: Text('Online Password',
|
||||||
DateTimeWebWidget(
|
style: text,
|
||||||
isTime: false,
|
),
|
||||||
isRequired: true,
|
value: 'Online Password',
|
||||||
title: 'Access Period',
|
groupValue: (state is PasswordTypeSelected)
|
||||||
size: size,
|
? state.selectedType
|
||||||
endTime: () {
|
: visitorBloc.accessTypeSelected,
|
||||||
visitorBloc.add(SelectTimeVisitorPassword(
|
onChanged: (String? value) {
|
||||||
context: context,
|
if (value != null) {
|
||||||
isStart: false,
|
context.read<VisitorPasswordBloc>()
|
||||||
isRepeat: false));
|
.add(SelectPasswordType(value));
|
||||||
},
|
}
|
||||||
startTime: () {
|
},
|
||||||
visitorBloc.add(SelectTimeVisitorPassword(
|
),
|
||||||
context: context,
|
),
|
||||||
isStart: true,
|
SizedBox(
|
||||||
isRepeat: false));
|
width: size.width * 0.15,
|
||||||
},
|
child: RadioListTile<String>(
|
||||||
firstString: visitorBloc.startTimeAccess.toString(),
|
title: Text('Offline Password',
|
||||||
secondString: visitorBloc.endTimeAccess.toString(),
|
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.15,
|
||||||
|
child: RadioListTile<String>(
|
||||||
|
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 = '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
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),),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
visitorBloc.accessTypeSelected == 'Dynamic Password'
|
||||||
height: 20,
|
? const SizedBox()
|
||||||
),
|
: Column(
|
||||||
Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: [
|
Row(
|
||||||
Row(
|
children: [
|
||||||
children: [
|
Text('* ',
|
||||||
Text(
|
style: Theme.of(context).textTheme.bodyMedium!
|
||||||
'* ',
|
.copyWith(color: Colors.red),
|
||||||
style: Theme.of(context)
|
),
|
||||||
.textTheme
|
Text('Usage Frequency',style:text ,),
|
||||||
.bodyMedium!
|
],
|
||||||
.copyWith(color: Colors.red),
|
),
|
||||||
),
|
Row(
|
||||||
Text('Access Devices',
|
children: <Widget>[
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
SizedBox(
|
||||||
color: Colors.black,fontSize: 13),),
|
width: 200,
|
||||||
],
|
child: RadioListTile<String>(
|
||||||
|
title: Text('One-Time',
|
||||||
|
style:text ,),
|
||||||
|
value: 'One-Time',
|
||||||
|
groupValue:
|
||||||
|
(state is UsageFrequencySelected)
|
||||||
|
? state.selectedFrequency
|
||||||
|
: visitorBloc.usageFrequencySelected,
|
||||||
|
onChanged: (String? value) {
|
||||||
|
if (value != null) {
|
||||||
|
context.read<VisitorPasswordBloc>()
|
||||||
|
.add(SelectUsageFrequency(value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 200,
|
||||||
|
child: RadioListTile<String>(
|
||||||
|
title: Text('Periodic',
|
||||||
|
style: text),
|
||||||
|
value: 'Periodic',
|
||||||
|
groupValue: (state is UsageFrequencySelected)
|
||||||
|
? state.selectedFrequency
|
||||||
|
: visitorBloc.usageFrequencySelected,
|
||||||
|
onChanged: (String? value) {
|
||||||
|
if (value != null) {
|
||||||
|
context.read<VisitorPasswordBloc>()
|
||||||
|
.add(SelectUsageFrequency(value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Text('Within the validity period, each device can be unlocked only once.',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
color: ColorsManager.grayColor,fontSize: 9),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
if ((visitorBloc.usageFrequencySelected != 'One-Time' ||
|
||||||
|
visitorBloc.accessTypeSelected != 'Offline Password') &&
|
||||||
|
(visitorBloc.usageFrequencySelected != ''))
|
||||||
|
DateTimeWebWidget(
|
||||||
|
isTime: false,
|
||||||
|
isRequired: true,
|
||||||
|
title: 'Access Period',
|
||||||
|
size: size,
|
||||||
|
endTime: () {
|
||||||
|
visitorBloc.add(SelectTimeVisitorPassword(
|
||||||
|
context: context,
|
||||||
|
isStart: false,
|
||||||
|
isRepeat: false));
|
||||||
|
},
|
||||||
|
startTime: () {
|
||||||
|
visitorBloc.add(SelectTimeVisitorPassword(
|
||||||
|
context: context,
|
||||||
|
isStart: true,
|
||||||
|
isRepeat: false));
|
||||||
|
},
|
||||||
|
firstString: visitorBloc.startTimeAccess.toString(),
|
||||||
|
secondString: visitorBloc.endTimeAccess.toString(),
|
||||||
),
|
),
|
||||||
Text(
|
const SizedBox(
|
||||||
'Within the validity period, each device can be unlocked only once.',
|
height: 20,
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
),
|
||||||
fontWeight: FontWeight.w400,
|
Column(
|
||||||
color: ColorsManager.grayColor,fontSize: 9),),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
const SizedBox(
|
children: [
|
||||||
height: 20,
|
Row(
|
||||||
),
|
children: [
|
||||||
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
Text('* ',
|
||||||
visitorBloc.accessTypeSelected == 'Online Password')
|
style: Theme.of(context).textTheme.bodyMedium!
|
||||||
SizedBox(
|
.copyWith(color: Colors.red),
|
||||||
width: 100,
|
),
|
||||||
child: Column(
|
Text('Access Devices',
|
||||||
children: [
|
style:text ,),
|
||||||
Text('Repeat',
|
],
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
),
|
||||||
color: Colors.black,fontSize: 13),),
|
Text(
|
||||||
Transform.scale(
|
'Within the validity period, each device can be unlocked only once.',
|
||||||
scale: .8,
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
child: CupertinoSwitch(
|
fontWeight: FontWeight.w400,
|
||||||
value: visitorBloc.repeat,
|
color: ColorsManager.grayColor,fontSize: 9),),
|
||||||
onChanged: (value) {
|
const SizedBox(
|
||||||
visitorBloc.add(ToggleRepeatEvent());
|
height: 20,
|
||||||
},
|
),
|
||||||
applyTheme: true,
|
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||||
),
|
visitorBloc.accessTypeSelected == 'Online Password')
|
||||||
),
|
SizedBox(
|
||||||
],
|
width: 100,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text('Repeat',
|
||||||
|
style:text),
|
||||||
|
Transform.scale(
|
||||||
|
scale: .8,
|
||||||
|
child: CupertinoSwitch(
|
||||||
|
value: visitorBloc.repeat,
|
||||||
|
onChanged: (value) {
|
||||||
|
visitorBloc.add(ToggleRepeatEvent());
|
||||||
|
},
|
||||||
|
applyTheme: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||||
|
visitorBloc.accessTypeSelected == 'Online Password')
|
||||||
|
isRepeat ? const RepeatWidget() : const SizedBox(),
|
||||||
|
Container(
|
||||||
|
decoration: containerDecoration,
|
||||||
|
width: size.width * 0.08,
|
||||||
|
child: DefaultButton(
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return const AddDeviceDialog();
|
||||||
|
},
|
||||||
|
).then((listDevice) {
|
||||||
|
if(listDevice!=null){
|
||||||
|
visitorBloc.selectedDevices = listDevice;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
borderRadius: 8,
|
||||||
|
child: Text('+ Add Device',style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: ColorsManager.whiteColors,fontSize: 12),),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
],
|
||||||
visitorBloc.accessTypeSelected == 'Online Password')
|
),
|
||||||
isRepeat ? const RepeatWidget() : const SizedBox(),
|
],
|
||||||
Container(
|
),
|
||||||
decoration: containerDecoration,
|
),
|
||||||
width: size.width * 0.08,
|
),
|
||||||
child: DefaultButton(
|
),
|
||||||
onPressed: () {
|
actionsAlignment: MainAxisAlignment.center,
|
||||||
showDialog(
|
actions: <Widget>[
|
||||||
context: context,
|
Container(
|
||||||
barrierDismissible: false,
|
decoration: containerDecoration,
|
||||||
builder: (BuildContext context) {
|
width: size.width * 0.2,
|
||||||
return const AddDeviceDialog();
|
child: DefaultButton(
|
||||||
},
|
borderRadius: 8,
|
||||||
).then((listDevice) {
|
onPressed: () {
|
||||||
if(listDevice!=null){
|
Navigator.of(context).pop(); // Close the dialog
|
||||||
print('selectedDevices==$listDevice');
|
},
|
||||||
visitorBloc.selectedDevices = listDevice;
|
backgroundColor: Colors.white,
|
||||||
|
child: Text(
|
||||||
|
'Cancel',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: ColorsManager.blackColor,fontSize: 16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
decoration: containerDecoration,
|
||||||
|
width: size.width * 0.2,
|
||||||
|
child: DefaultButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (visitorBloc.forgetFormKey.currentState!.validate()) {
|
||||||
|
if(visitorBloc.selectedDevices.isNotEmpty){
|
||||||
|
if(visitorBloc.effectiveTimeTimeStamp!=null&&visitorBloc.expirationTimeTimeStamp!=null) {
|
||||||
|
setPasswordFunction(context, size, visitorBloc);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
visitorBloc.stateDialog(context:
|
||||||
|
context,message: 'Please select Access Period to continue',title: 'Access Period');
|
||||||
|
}
|
||||||
|
}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,
|
||||||
|
color: ColorsManager.whiteColors,fontSize: 16),),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
); },
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
}
|
);
|
||||||
});
|
}
|
||||||
|
|
||||||
},
|
Future<void> setPasswordFunction(
|
||||||
borderRadius: 8,
|
BuildContext context,
|
||||||
child: Text('+ Add Device',style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
Size size,
|
||||||
fontWeight: FontWeight.w400,
|
VisitorPasswordBloc visitorBloc,
|
||||||
color: ColorsManager.whiteColors,fontSize: 12),),
|
) {
|
||||||
|
return showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
if (state is LoadingInitialState) {
|
||||||
|
// Show loading indicator while loading
|
||||||
|
return AlertDialog(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
content: SizedBox(
|
||||||
|
height: size.height * 0.25,
|
||||||
|
child: Center(
|
||||||
|
child: CircularProgressIndicator(), // Display a loading spinner
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
return AlertDialog(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
content: SizedBox(
|
||||||
|
height: size.height * 0.25,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
Assets.deviceNoteIcon,
|
||||||
|
height: 35,
|
||||||
|
width: 35,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Set Password',
|
||||||
|
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||||
|
fontSize: 30,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
const SizedBox(width: 15),
|
||||||
|
Text(
|
||||||
|
'This action will update all of the selected\n door locks passwords in the property.\n\nAre you sure you want to continue?',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
actionsAlignment: MainAxisAlignment.center,
|
||||||
),
|
actions: <Widget>[
|
||||||
actionsAlignment: MainAxisAlignment.center,
|
Container(
|
||||||
actions: <Widget>[
|
decoration: containerDecoration,
|
||||||
Container(
|
width: size.width * 0.1,
|
||||||
decoration: containerDecoration,
|
child: DefaultButton(
|
||||||
width: size.width * 0.2,
|
borderRadius: 8,
|
||||||
child: DefaultButton(
|
onPressed: () {
|
||||||
borderRadius: 8,
|
Navigator.of(context).pop();
|
||||||
onPressed: () {
|
},
|
||||||
Navigator.of(context).pop(); // Close the dialog
|
backgroundColor: Colors.white,
|
||||||
},
|
child: Text(
|
||||||
backgroundColor: Colors.white,
|
'Cancel',
|
||||||
child: Text(
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
'Cancel',
|
fontWeight: FontWeight.w400,
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
color: ColorsManager.blackColor,
|
||||||
fontWeight: FontWeight.w400,
|
fontSize: 16,
|
||||||
color: ColorsManager.blackColor,fontSize: 16),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
Container(
|
||||||
),
|
decoration: containerDecoration,
|
||||||
Container(
|
width: size.width * 0.1,
|
||||||
decoration: containerDecoration,
|
child: DefaultButton(
|
||||||
width: size.width * 0.2,
|
borderRadius: 8,
|
||||||
child: DefaultButton(
|
onPressed: () {
|
||||||
onPressed: () {
|
Navigator.pop(context);
|
||||||
if (visitorBloc.forgetFormKey.currentState!.validate()) {
|
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
||||||
showDialog(
|
visitorBloc.accessTypeSelected == 'Online Password') {
|
||||||
context: context,
|
visitorBloc.add(OnlineOneTimePasswordEvent(
|
||||||
barrierDismissible: false,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
passwordName: visitorBloc.userNameController.text,
|
||||||
return InfoDialog(
|
email: visitorBloc.emailController.text,
|
||||||
size: size,
|
));
|
||||||
title: 'Set Password',
|
} else if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||||
content:
|
visitorBloc.accessTypeSelected == 'Online Password') {
|
||||||
'This action will update all of the selected\n door locks passwords in the property.\n\nAre you sure you want to continue?',
|
visitorBloc.add(OnlineMultipleTimePasswordEvent(
|
||||||
actions: [
|
passwordName: visitorBloc.userNameController.text,
|
||||||
Container(
|
email: visitorBloc.emailController.text,
|
||||||
decoration: containerDecoration,
|
effectiveTime: visitorBloc.effectiveTimeTimeStamp.toString(),
|
||||||
width: size.width * 0.1,
|
invalidTime: visitorBloc.expirationTimeTimeStamp.toString(),
|
||||||
child: DefaultButton(
|
));
|
||||||
borderRadius: 8,
|
} else if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
||||||
onPressed: () {
|
visitorBloc.accessTypeSelected == 'Offline Password') {
|
||||||
Navigator.of(context).pop();
|
visitorBloc.add(OfflineOneTimePasswordEvent(
|
||||||
},
|
context: context,
|
||||||
backgroundColor: Colors.white,
|
passwordName: visitorBloc.userNameController.text,
|
||||||
child: Text(
|
email: visitorBloc.emailController.text,
|
||||||
'Cancel',
|
));
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
} else if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||||
fontWeight: FontWeight.w400,
|
visitorBloc.accessTypeSelected == 'Offline Password') {
|
||||||
color: ColorsManager.blackColor,fontSize: 16),
|
visitorBloc.add(OfflineMultipleTimePasswordEvent(
|
||||||
),
|
passwordName: visitorBloc.userNameController.text,
|
||||||
),
|
email: visitorBloc.emailController.text,
|
||||||
),
|
effectiveTime: visitorBloc.effectiveTimeTimeStamp.toString(),
|
||||||
Container(
|
invalidTime: visitorBloc.expirationTimeTimeStamp.toString(),
|
||||||
decoration: containerDecoration,
|
));
|
||||||
width: size.width * 0.1,
|
}
|
||||||
child: DefaultButton(
|
},
|
||||||
borderRadius: 8,
|
child: Text(
|
||||||
onPressed: () {
|
'Ok',
|
||||||
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
visitorBloc.accessTypeSelected == 'Online Password') {
|
fontWeight: FontWeight.w400,
|
||||||
visitorBloc.add(
|
color: ColorsManager.whiteColors,
|
||||||
OnlineOneTimePasswordEvent(
|
fontSize: 16,
|
||||||
context: context,
|
),
|
||||||
passwordName: visitorBloc.userNameController.text,
|
),
|
||||||
email: visitorBloc.emailController.text));
|
),
|
||||||
} else if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
),
|
||||||
visitorBloc.accessTypeSelected == 'Online Password') {
|
],
|
||||||
visitorBloc.add(OnlineMultipleTimePasswordEvent(
|
);
|
||||||
passwordName: visitorBloc.userNameController.text,
|
}
|
||||||
email: visitorBloc.emailController.text,
|
},
|
||||||
effectiveTime: visitorBloc.effectiveTimeTimeStamp.toString(),
|
);
|
||||||
invalidTime: visitorBloc.expirationTimeTimeStamp.toString()));
|
},
|
||||||
} else if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
|
||||||
visitorBloc.accessTypeSelected == 'Offline Password') {
|
|
||||||
visitorBloc.add(OfflineOneTimePasswordEvent(
|
|
||||||
passwordName: visitorBloc.userNameController.text,
|
|
||||||
email: visitorBloc.emailController.text,
|
|
||||||
));
|
|
||||||
} else if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
|
||||||
visitorBloc.accessTypeSelected == 'Offline Password') {
|
|
||||||
visitorBloc.add(
|
|
||||||
OfflineMultipleTimePasswordEvent(
|
|
||||||
passwordName: visitorBloc.userNameController.text,
|
|
||||||
email: visitorBloc.emailController.text,
|
|
||||||
effectiveTime: visitorBloc.effectiveTimeTimeStamp.toString(),
|
|
||||||
invalidTime: visitorBloc.expirationTimeTimeStamp.toString()));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text('Ok',
|
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
color: ColorsManager.whiteColors,fontSize: 16),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
borderRadius: 8,
|
|
||||||
child: Text('Ok', style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
color: ColorsManager.whiteColors,fontSize: 16),),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,11 @@ import 'dart:convert';
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/model/password_model.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/schedule_model.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/services/api/http_service.dart';
|
||||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||||
|
|
||||||
import '../pages/visitor_password/model/device_model.dart';
|
|
||||||
|
|
||||||
class AccessMangApi{
|
class AccessMangApi{
|
||||||
|
|
||||||
Future<List<PasswordModel>> fetchVisitorPassword() async {
|
Future<List<PasswordModel>> fetchVisitorPassword() async {
|
||||||
@ -17,7 +16,6 @@ class AccessMangApi{
|
|||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json;
|
List<dynamic> jsonData = json;
|
||||||
print('Password List: $json');
|
|
||||||
List<PasswordModel> passwordList = jsonData.map((jsonItem) {
|
List<PasswordModel> passwordList = jsonData.map((jsonItem) {
|
||||||
return PasswordModel.fromJson(jsonItem);
|
return PasswordModel.fromJson(jsonItem);
|
||||||
}).toList();
|
}).toList();
|
||||||
@ -38,7 +36,6 @@ class AccessMangApi{
|
|||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json;
|
List<dynamic> jsonData = json;
|
||||||
print('fetchDevices List: $json');
|
|
||||||
List<DeviceModel> passwordList = jsonData.map((jsonItem) {
|
List<DeviceModel> passwordList = jsonData.map((jsonItem) {
|
||||||
return DeviceModel.fromJson(jsonItem);
|
return DeviceModel.fromJson(jsonItem);
|
||||||
}).toList();
|
}).toList();
|
||||||
@ -60,18 +57,6 @@ class AccessMangApi{
|
|||||||
String? invalidTime,
|
String? invalidTime,
|
||||||
List<String>? devicesUuid}) async {
|
List<String>? devicesUuid}) async {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
print('postOfflineOneTime List: ${
|
|
||||||
jsonEncode({
|
|
||||||
"email": email,
|
|
||||||
"passwordName": passwordName,
|
|
||||||
"password": password,
|
|
||||||
"devicesUuid": devicesUuid,
|
|
||||||
"effectiveTime":effectiveTime ,
|
|
||||||
"invalidTime": invalidTime
|
|
||||||
})
|
|
||||||
}');
|
|
||||||
|
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOnlineOneTime,
|
path: ApiEndpoints.sendOnlineOneTime,
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
@ -84,7 +69,6 @@ class AccessMangApi{
|
|||||||
}),
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
print('postOfflineOneTime List: $json');
|
|
||||||
if(json['statusCode'].toString()=='201'){
|
if(json['statusCode'].toString()=='201'){
|
||||||
return true;
|
return true;
|
||||||
}else{
|
}else{
|
||||||
@ -93,9 +77,8 @@ class AccessMangApi{
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
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;
|
||||||
}
|
}
|
||||||
@ -121,15 +104,11 @@ class AccessMangApi{
|
|||||||
if (scheduleList != null) {
|
if (scheduleList != null) {
|
||||||
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
|
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
|
||||||
}
|
}
|
||||||
print('createPassword =${jsonEncode(body)}');
|
|
||||||
|
|
||||||
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) {
|
||||||
print('createPassword =${json}');
|
|
||||||
|
|
||||||
if(json['data']['successOperations'][0]['success'].toString()=='true'){
|
if(json['data']['successOperations'][0]['success'].toString()=='true'){
|
||||||
return true;
|
return true;
|
||||||
}else{
|
}else{
|
||||||
@ -138,7 +117,7 @@ class AccessMangApi{
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
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;
|
||||||
@ -149,15 +128,6 @@ class AccessMangApi{
|
|||||||
|
|
||||||
Future postOffLineOneTime({String? email,String? passwordName,List<String>? devicesUuid}) async {
|
Future postOffLineOneTime({String? email,String? passwordName,List<String>? devicesUuid}) async {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
print('postOfflineOneTime List: ${
|
|
||||||
{
|
|
||||||
"email": email,
|
|
||||||
"passwordName": passwordName,
|
|
||||||
"devicesUuid": devicesUuid
|
|
||||||
}
|
|
||||||
}');
|
|
||||||
|
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOffLineOneTime,
|
path: ApiEndpoints.sendOffLineOneTime,
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
@ -166,10 +136,14 @@ class AccessMangApi{
|
|||||||
"devicesUuid": devicesUuid
|
"devicesUuid": devicesUuid
|
||||||
}),
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json;
|
if (json['data']['successOperations'][0]['success'].toString() ==
|
||||||
print('postOfflineOneTime List: $json');
|
'true') {
|
||||||
},
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -187,15 +161,6 @@ class AccessMangApi{
|
|||||||
|
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
print('postOfflineOneTime List: ${
|
|
||||||
{
|
|
||||||
"email": email,
|
|
||||||
"passwordName": passwordName,
|
|
||||||
"devicesUuid": devicesUuid
|
|
||||||
}
|
|
||||||
}');
|
|
||||||
|
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOffLineOneTime,
|
path: ApiEndpoints.sendOffLineOneTime,
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
@ -206,10 +171,14 @@ class AccessMangApi{
|
|||||||
"invalidTime": invalidTime
|
"invalidTime": invalidTime
|
||||||
}),
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<dynamic> jsonData = json;
|
if (json['data']['successOperations'][0]['success'].toString() ==
|
||||||
print('postOfflineOneTime List: $json');
|
'true') {
|
||||||
},
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
@ -8,9 +7,7 @@ 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 AuthenticationAPI {
|
class AuthenticationAPI {
|
||||||
|
|
||||||
static Future<Token> loginWithEmail({required var model}) async {
|
static Future<Token> loginWithEmail({required var model}) async {
|
||||||
print('model=$model');
|
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.login,
|
path: ApiEndpoints.login,
|
||||||
body: model.toJson(),
|
body: model.toJson(),
|
||||||
@ -46,19 +43,15 @@ class AuthenticationAPI {
|
|||||||
},
|
},
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
print('object==$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) {
|
||||||
// Handle 400 Bad Request
|
|
||||||
final errorData = e.response!.data;
|
final errorData = e.response!.data;
|
||||||
String errorMessage = errorData['message'];
|
String errorMessage = errorData['message'];
|
||||||
debugPrint('Unexpected Error: $errorMessage');
|
|
||||||
if(errorMessage=='User not found'){
|
if(errorMessage=='User not found'){
|
||||||
return 1;
|
return 1;
|
||||||
}else{
|
}else{
|
||||||
@ -87,8 +80,6 @@ class AuthenticationAPI {
|
|||||||
body: {"email": email, "type": "PASSWORD", "otpCode": otpCode},
|
body: {"email": email, "type": "PASSWORD", "otpCode": otpCode},
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
print('json=$json');
|
|
||||||
|
|
||||||
if (json['message'] == 'Otp Verified Successfully') {
|
if (json['message'] == 'Otp Verified Successfully') {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -99,12 +90,9 @@ class AuthenticationAPI {
|
|||||||
}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) {
|
||||||
// Handle 400 Bad Request
|
|
||||||
final errorData = e.response!.data;
|
final errorData = e.response!.data;
|
||||||
String errorMessage = errorData['message'];
|
String errorMessage = errorData['message'];
|
||||||
debugPrint('Unexpected Error: $errorMessage');
|
|
||||||
return errorMessage;
|
return errorMessage;
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debugPrint('Error: ${e.message}');
|
debugPrint('Error: ${e.message}');
|
||||||
|
@ -3,14 +3,12 @@ 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(
|
||||||
|
Reference in New Issue
Block a user