mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
create visitor password
This commit is contained in:
@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
||||
import 'package:syncrow_web/services/access_mang_api.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||
|
||||
@ -9,15 +11,29 @@ import 'package:syncrow_web/utils/snack_bar.dart';
|
||||
class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordState> {
|
||||
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
|
||||
on<SelectUsageFrequency>(selectUsageFrequency);
|
||||
on<FetchDevice>(_onFetchDevice);
|
||||
|
||||
on<SelectPasswordType>(selectAccessType);
|
||||
on<SelectTimeVisitorPassword>(selectTimeVisitorPassword);
|
||||
on<ToggleRepeatEvent>(toggleRepeat);
|
||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||
|
||||
}
|
||||
final TextEditingController userNameController = TextEditingController();
|
||||
final TextEditingController emailController = TextEditingController();
|
||||
|
||||
|
||||
|
||||
final TextEditingController deviceNameController = TextEditingController();
|
||||
final TextEditingController deviceIdController = TextEditingController();
|
||||
final TextEditingController unitNameController = TextEditingController();
|
||||
final TextEditingController virtualAddressController = TextEditingController();
|
||||
|
||||
List<DeviceModel> data=[];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
String accessTypeSelected='Offline Password';
|
||||
String usageFrequencySelected='One-Time';
|
||||
|
||||
@ -136,6 +152,17 @@ class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordStat
|
||||
}
|
||||
emit(ChangeTimeState());
|
||||
}
|
||||
//Add Accessible Device
|
||||
|
||||
Future<void> _onFetchDevice(
|
||||
FetchDevice event, Emitter<VisitorPasswordState> emit) async {
|
||||
try {
|
||||
emit(DeviceLoaded());
|
||||
data = await AccessMangApi().fetchDevices();
|
||||
emit(TableLoaded(data));
|
||||
} catch (e) {
|
||||
emit(FailedState(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -47,3 +47,4 @@ class ToggleDaySelectionEvent extends VisitorPasswordEvent {
|
||||
|
||||
|
||||
class ToggleRepeatEvent extends VisitorPasswordEvent {}
|
||||
class FetchDevice extends VisitorPasswordEvent {}
|
||||
|
@ -1,6 +1,7 @@
|
||||
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
||||
|
||||
abstract class VisitorPasswordState extends Equatable {
|
||||
const VisitorPasswordState();
|
||||
@ -42,3 +43,20 @@ class IsRepeatState extends VisitorPasswordState {
|
||||
|
||||
class LoadingInitialState extends VisitorPasswordState {}
|
||||
class ChangeTimeState extends VisitorPasswordState {}
|
||||
class DeviceLoaded extends VisitorPasswordState {}
|
||||
class FailedState extends VisitorPasswordState {
|
||||
final String message;
|
||||
|
||||
FailedState(this.message);
|
||||
|
||||
@override
|
||||
List<Object> get props => [message];
|
||||
}
|
||||
class TableLoaded extends VisitorPasswordState {
|
||||
final List<DeviceModel> data;
|
||||
|
||||
const TableLoaded(this.data);
|
||||
|
||||
@override
|
||||
List<Object> get props => [data];
|
||||
}
|
99
lib/pages/visitor_password/model/device_model.dart
Normal file
99
lib/pages/visitor_password/model/device_model.dart
Normal file
@ -0,0 +1,99 @@
|
||||
|
||||
|
||||
class DeviceModel {
|
||||
dynamic productUuid;
|
||||
dynamic productType;
|
||||
dynamic activeTime;
|
||||
dynamic category;
|
||||
dynamic categoryName;
|
||||
dynamic createTime;
|
||||
dynamic gatewayId;
|
||||
dynamic icon;
|
||||
dynamic ip;
|
||||
dynamic lat;
|
||||
dynamic localKey;
|
||||
dynamic lon;
|
||||
dynamic model;
|
||||
dynamic name;
|
||||
dynamic online;
|
||||
dynamic ownerId;
|
||||
dynamic sub;
|
||||
dynamic timeZone;
|
||||
dynamic updateTime;
|
||||
dynamic uuid;
|
||||
|
||||
DeviceModel({
|
||||
required this.productUuid,
|
||||
required this.productType,
|
||||
required this.activeTime,
|
||||
required this.category,
|
||||
required this.categoryName,
|
||||
required this.createTime,
|
||||
required this.gatewayId,
|
||||
required this.icon,
|
||||
required this.ip,
|
||||
required this.lat,
|
||||
required this.localKey,
|
||||
required this.lon,
|
||||
required this.model,
|
||||
required this.name,
|
||||
required this.online,
|
||||
required this.ownerId,
|
||||
required this.sub,
|
||||
required this.timeZone,
|
||||
required this.updateTime,
|
||||
required this.uuid,
|
||||
});
|
||||
|
||||
// Deserialize from JSON
|
||||
factory DeviceModel.fromJson(Map<String, dynamic> json) {
|
||||
return DeviceModel(
|
||||
productUuid: json['productUuid'] ,
|
||||
productType: json['productType'],
|
||||
activeTime: json['activeTime'],
|
||||
category: json['category'] ,
|
||||
categoryName: json['categoryName'] ,
|
||||
createTime: json['createTime'] ,
|
||||
gatewayId: json['gatewayId'],
|
||||
icon: json['icon'],
|
||||
ip: json['ip'] ,
|
||||
lat: json['lat'] ,
|
||||
localKey: json['localKey'] ,
|
||||
lon: json['lon'] ,
|
||||
model: json['model'] ,
|
||||
name: json['name'],
|
||||
online: json['online'],
|
||||
ownerId: json['ownerId'] ,
|
||||
sub: json['sub'],
|
||||
timeZone: json['timeZone'],
|
||||
updateTime: json['updateTime'] ,
|
||||
uuid: json['uuid'],
|
||||
);
|
||||
}
|
||||
|
||||
// Serialize to JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'productUuid': productUuid,
|
||||
'productType': productType,
|
||||
'activeTime': activeTime,
|
||||
'category': category,
|
||||
'categoryName': categoryName,
|
||||
'createTime': createTime,
|
||||
'gatewayId': gatewayId,
|
||||
'icon': icon,
|
||||
'ip': ip,
|
||||
'lat': lat,
|
||||
'localKey': localKey,
|
||||
'lon': lon,
|
||||
'model': model,
|
||||
'name': name,
|
||||
'online': online,
|
||||
'ownerId': ownerId,
|
||||
'sub': sub,
|
||||
'timeZone': timeZone,
|
||||
'updateTime': updateTime,
|
||||
'uuid': uuid,
|
||||
};
|
||||
}
|
||||
}
|
210
lib/pages/visitor_password/view/add_device_dialog.dart
Normal file
210
lib/pages/visitor_password/view/add_device_dialog.dart
Normal file
@ -0,0 +1,210 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/pages/common/custom_web_textfield.dart';
|
||||
import 'package:syncrow_web/pages/common/default_button.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
import '../../common/custom_table.dart';
|
||||
|
||||
|
||||
class AddDeviceDialog extends StatelessWidget {
|
||||
const AddDeviceDialog({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Size size = MediaQuery.of(context).size;
|
||||
return BlocProvider(
|
||||
create: (context) => VisitorPasswordBloc()..add(FetchDevice()),
|
||||
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||
builder: (BuildContext context, VisitorPasswordState state) {
|
||||
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||
return AlertDialog(
|
||||
backgroundColor: Colors.white,
|
||||
title: const Text('Add Accessible Device'),
|
||||
content: Container(
|
||||
height: MediaQuery.of(context).size.height/1.7,
|
||||
width: MediaQuery.of(context).size.width/2,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: size.width,
|
||||
padding: EdgeInsets.all(15),
|
||||
decoration:containerDecoration.copyWith(
|
||||
color: ColorsManager.worningColor,
|
||||
border: Border.all(color: Color(0xffFFD22F)),
|
||||
boxShadow: []
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
child: SvgPicture.asset(
|
||||
Assets.deviceNoteIcon,
|
||||
height: 15,
|
||||
width: 15,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10,),
|
||||
Text('Only online accessible devices can be added'),
|
||||
],
|
||||
)
|
||||
),
|
||||
SizedBox(height: 20,),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: CustomWebTextField(
|
||||
controller: visitorBloc.deviceNameController,
|
||||
isRequired: true,
|
||||
textFieldName: 'Device Name',
|
||||
description: '',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: CustomWebTextField(
|
||||
controller: visitorBloc.deviceNameController,
|
||||
isRequired: true,
|
||||
textFieldName: 'Device ID',
|
||||
description: '',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: CustomWebTextField(
|
||||
controller: visitorBloc.unitNameController,
|
||||
isRequired: true,
|
||||
textFieldName: 'Unit Name',
|
||||
description: '',
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(width: 10),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: Container(
|
||||
height: 43,
|
||||
width: 100,
|
||||
decoration: containerDecoration,
|
||||
child: Center(
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
// Your search function here
|
||||
},
|
||||
borderRadius: 9,
|
||||
child: const Text('Search'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 25),
|
||||
|
||||
Center(
|
||||
child: Container(
|
||||
height: 43,
|
||||
width: 100,
|
||||
decoration: containerDecoration,
|
||||
child: Center(
|
||||
child: DefaultButton(
|
||||
backgroundColor: ColorsManager.whiteColors,
|
||||
borderRadius: 9,
|
||||
child: Text(
|
||||
'Reset',
|
||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Container(
|
||||
child: Expanded(
|
||||
child: state is TableLoaded
|
||||
? Container(
|
||||
decoration: containerDecoration,
|
||||
child: DynamicTable(
|
||||
size: size*0.5,
|
||||
headers: ['Device Name', 'Device ID', 'Access Type', 'Unit Name', 'Status'],
|
||||
data: state.data.map((item) {
|
||||
return [
|
||||
item.name.toString(),
|
||||
item.uuid.toString(),
|
||||
item.productType.toString(),
|
||||
'',
|
||||
item.online.toString(),
|
||||
// item.categoryName.toString(),
|
||||
// accessBloc.timestampToDateTime(item.effectiveTime).toString(),
|
||||
// accessBloc.timestampToDateTime(item.invalidTime).toString(),
|
||||
// item.deviceUuid.toString(),
|
||||
// item.passwordCreated != null ? accessBloc.timestampToDateTime(item.passwordCreated).toString() : 'no data',
|
||||
// item.passwordStatus.toString(),
|
||||
];
|
||||
}).toList(),
|
||||
),
|
||||
)
|
||||
// TableWidget(size: size, headers: ['Device Name', 'Device ID', 'Access Type', 'Unit Name', 'Status', 'Virtual Address',], data: [], bloc: bloc)
|
||||
: const Center(child: CircularProgressIndicator())),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
actionsAlignment: MainAxisAlignment.center,
|
||||
actions: <Widget>[
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.2,
|
||||
child: DefaultButton(
|
||||
borderRadius: 8,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // Close the dialog
|
||||
},
|
||||
backgroundColor: Colors.white,
|
||||
child: Text(
|
||||
'Cancel',
|
||||
style: Theme.of(context).textTheme.bodyMedium!,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.2,
|
||||
child: const DefaultButton(
|
||||
borderRadius: 8,
|
||||
child: Text('Ok'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
); }
|
||||
}
|
@ -7,8 +7,8 @@ import 'package:syncrow_web/pages/common/default_button.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/view/add_device_dialog.dart';
|
||||
import 'package:syncrow_web/pages/visitor_password/view/repeat_widget.dart';
|
||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
|
||||
class VisitorPasswordDialog extends StatelessWidget {
|
||||
@ -24,216 +24,242 @@ class VisitorPasswordDialog extends StatelessWidget {
|
||||
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||
bool isRepeat = state is IsRepeatState ? state.repeat : visitorBloc.repeat;
|
||||
return AlertDialog(
|
||||
backgroundColor: Colors.white,
|
||||
title: const Text('Create visitor password'),
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: CustomWebTextField(
|
||||
controller: visitorBloc.userNameController,
|
||||
isRequired: true,
|
||||
textFieldName: 'User Name',
|
||||
description: '',
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: CustomWebTextField(
|
||||
controller: visitorBloc.emailController,
|
||||
isRequired: true,
|
||||
textFieldName: 'Email Address',
|
||||
description: 'The password will be sent to the visitor’s email address.',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: size.height * 0.02), // Add spacing
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: ListBody(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'* ',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(color: Colors.red),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: CustomWebTextField(
|
||||
controller: visitorBloc.userNameController,
|
||||
isRequired: true,
|
||||
textFieldName: 'Name',
|
||||
description: '',
|
||||
),
|
||||
),
|
||||
const Text('Access Type'),
|
||||
const Spacer(),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: CustomWebTextField(
|
||||
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>[
|
||||
SizedBox(
|
||||
width: size.width * 0.15,
|
||||
child: RadioListTile<String>(
|
||||
title: const Text('Offline Password'),
|
||||
value: 'Offline Password',
|
||||
groupValue: (state is PasswordTypeSelected)
|
||||
? state.selectedType
|
||||
: visitorBloc.accessTypeSelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
SizedBox(height: 20,),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'* ',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(color: Colors.red),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: size.width * 0.15,
|
||||
child: RadioListTile<String>(
|
||||
title: const Text('Online Password'),
|
||||
value: 'Online Password',
|
||||
groupValue: (state is PasswordTypeSelected)
|
||||
? state.selectedType
|
||||
: visitorBloc.accessTypeSelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
||||
}
|
||||
},
|
||||
const Text('Access Type'),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
width: size.width * 0.15,
|
||||
child: RadioListTile<String>(
|
||||
title: const Text('Offline Password'),
|
||||
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: const Text('Dynamic Password'),
|
||||
value: 'Dynamic 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: const Text('Online Password'),
|
||||
value: 'Online Password',
|
||||
groupValue: (state is PasswordTypeSelected)
|
||||
? state.selectedType
|
||||
: visitorBloc.accessTypeSelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
visitorBloc.accessTypeSelected=='Dynamic Password' ?
|
||||
SizedBox():
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'* ',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(color: Colors.red),
|
||||
),
|
||||
const Text('Usage Frequency'),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
width: 200,
|
||||
child: RadioListTile<String>(
|
||||
title: const Text('One-Time'),
|
||||
value: 'One-Time',
|
||||
groupValue: (state is UsageFrequencySelected)
|
||||
? state.selectedFrequency
|
||||
: visitorBloc.usageFrequencySelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
|
||||
}
|
||||
},
|
||||
SizedBox(
|
||||
width: size.width * 0.15,
|
||||
child: RadioListTile<String>(
|
||||
title: const Text('Dynamic Password'),
|
||||
value: 'Dynamic Password',
|
||||
groupValue: (state is PasswordTypeSelected)
|
||||
? state.selectedType
|
||||
: visitorBloc.accessTypeSelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 200,
|
||||
child: RadioListTile<String>(
|
||||
title: const Text('Periodic'),
|
||||
value: 'Periodic',
|
||||
groupValue: (state is UsageFrequencySelected)
|
||||
? state.selectedFrequency
|
||||
: visitorBloc.usageFrequencySelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
|
||||
}
|
||||
},
|
||||
],
|
||||
),
|
||||
const 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'),
|
||||
SizedBox(height: 20,)
|
||||
],
|
||||
),
|
||||
visitorBloc.accessTypeSelected=='Dynamic Password' ?
|
||||
SizedBox():
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'* ',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(color: Colors.red),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
visitorBloc.accessTypeSelected=='Dynamic Password' ?
|
||||
SizedBox():
|
||||
const Text('Usage Frequency'),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
width: 200,
|
||||
child: RadioListTile<String>(
|
||||
title: const Text('One-Time'),
|
||||
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: const Text('Periodic'),
|
||||
value: 'Periodic',
|
||||
groupValue: (state is UsageFrequencySelected)
|
||||
? state.selectedFrequency
|
||||
: visitorBloc.usageFrequencySelected,
|
||||
onChanged: (String? value) {
|
||||
if (value != null) {
|
||||
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
DateTimeWebWidget(
|
||||
isRequired: true,
|
||||
title: 'Access Period',
|
||||
size: size,
|
||||
endTime: () {
|
||||
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: false));
|
||||
},
|
||||
startTime: () {
|
||||
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: true));
|
||||
},
|
||||
firstString: visitorBloc.startTime,
|
||||
secondString: visitorBloc.endTime,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'* ',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(color: Colors.red),
|
||||
),
|
||||
const Text('Access Devices'),
|
||||
],
|
||||
),
|
||||
const Text('Within the validity period, each device can be unlocked only once.'),
|
||||
visitorBloc.usageFrequencySelected=='Periodic'&&visitorBloc.accessTypeSelected=='Offline Password'?
|
||||
SizedBox(
|
||||
width: 100,
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const Text('Repeat'),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: visitorBloc.repeat,
|
||||
onChanged: (value) {
|
||||
visitorBloc.add(ToggleRepeatEvent());
|
||||
},
|
||||
applyTheme: true,
|
||||
Text('Within the validity period, each device can be unlocked only once.')
|
||||
],
|
||||
),
|
||||
|
||||
const SizedBox(height: 20,),
|
||||
|
||||
visitorBloc.accessTypeSelected=='Dynamic Password' ?
|
||||
SizedBox():
|
||||
DateTimeWebWidget(
|
||||
isRequired: true,
|
||||
title: 'Access Period',
|
||||
size: size,
|
||||
endTime: () {
|
||||
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: false));
|
||||
},
|
||||
startTime: () {
|
||||
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: true));
|
||||
},
|
||||
firstString: visitorBloc.startTime,
|
||||
secondString: visitorBloc.endTime,
|
||||
),
|
||||
const SizedBox(height: 20,),
|
||||
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'* ',
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(color: Colors.red),
|
||||
),
|
||||
const Text('Access Devices'),
|
||||
],
|
||||
),
|
||||
const Text('Within the validity period, each device can be unlocked only once.'),
|
||||
const SizedBox(height: 20,),
|
||||
visitorBloc.usageFrequencySelected=='Periodic'&&visitorBloc.accessTypeSelected=='Offline Password'?
|
||||
SizedBox(
|
||||
width: 100,
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const Text('Repeat'),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: visitorBloc.repeat,
|
||||
onChanged: (value) {
|
||||
visitorBloc.add(ToggleRepeatEvent());
|
||||
},
|
||||
applyTheme: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
):const SizedBox(),
|
||||
isRepeat ? const RepeatWidget() : const SizedBox(),
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.2,
|
||||
child: const DefaultButton(
|
||||
borderRadius: 8,
|
||||
child: Text('+ Add Device'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
):const SizedBox(),
|
||||
isRepeat ? const RepeatWidget() : const SizedBox(),
|
||||
Container(
|
||||
decoration: containerDecoration,
|
||||
width: size.width * 0.1,
|
||||
child: DefaultButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return const AddDeviceDialog();
|
||||
|
||||
],
|
||||
},
|
||||
);
|
||||
},
|
||||
borderRadius: 8,
|
||||
child: Text('+ Add Device'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
actionsAlignment: MainAxisAlignment.center,
|
||||
|
Reference in New Issue
Block a user