mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
add device filter and select time repeat widget
This commit is contained in:
@ -59,7 +59,7 @@ class MyApp extends StatelessWidget {
|
|||||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), // Set up color scheme
|
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), // Set up color scheme
|
||||||
useMaterial3: true, // Enable Material 3
|
useMaterial3: true, // Enable Material 3
|
||||||
),
|
),
|
||||||
// home: VisitorPasswordDialog()
|
// home: AddDeviceDialog()
|
||||||
home:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
|
home:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -237,7 +237,7 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
? DynamicTable(
|
? DynamicTable(
|
||||||
withCheckBox: false,
|
withCheckBox: false,
|
||||||
size: size,
|
size: size,
|
||||||
// cellDecoration: containerDecoration,
|
cellDecoration: containerDecoration,
|
||||||
headers: const [
|
headers: const [
|
||||||
'Name',
|
'Name',
|
||||||
'Access Type',
|
'Access Type',
|
||||||
|
@ -155,7 +155,7 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
return Expanded(
|
return Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 80,
|
height: 80,
|
||||||
padding: const EdgeInsets.all(20.0),
|
padding: const EdgeInsets.all(15.0),
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
bottom: BorderSide(
|
bottom: BorderSide(
|
||||||
|
@ -72,7 +72,10 @@ class CustomWebTextField extends StatelessWidget {
|
|||||||
controller: controller,
|
controller: controller,
|
||||||
style: const TextStyle(color: Colors.black),
|
style: const TextStyle(color: Colors.black),
|
||||||
decoration: textBoxDecoration()!
|
decoration: textBoxDecoration()!
|
||||||
.copyWith(hintText: 'Please enter'),
|
.copyWith(
|
||||||
|
errorStyle: const TextStyle(height: 0), // Hide the error text space
|
||||||
|
|
||||||
|
hintText: 'Please enter'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
74
lib/pages/common/info_dialog.dart
Normal file
74
lib/pages/common/info_dialog.dart
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
|
class InfoDialog extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final String content;
|
||||||
|
final Size? size;
|
||||||
|
final List<Widget>? actions;
|
||||||
|
|
||||||
|
InfoDialog({
|
||||||
|
required this.title,
|
||||||
|
required this.content,
|
||||||
|
this.actions,
|
||||||
|
this.size,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
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(
|
||||||
|
title,
|
||||||
|
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||||
|
fontSize: 30,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: Colors.black),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 15,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
content,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 18),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actionsAlignment: MainAxisAlignment.center,
|
||||||
|
actions: actions ??
|
||||||
|
<Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ class VisitorPasswordBloc
|
|||||||
on<ToggleRepeatEvent>(toggleRepeat);
|
on<ToggleRepeatEvent>(toggleRepeat);
|
||||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||||
on<SelectDeviceEvent>(selectDevice);
|
on<SelectDeviceEvent>(selectDevice);
|
||||||
|
on<UpdateFilteredDevicesEvent>(_onUpdateFilteredDevices);
|
||||||
|
|
||||||
on<OnlineOneTimePasswordEvent>(postOnlineOneTimePassword);
|
on<OnlineOneTimePasswordEvent>(postOnlineOneTimePassword);
|
||||||
on<OnlineMultipleTimePasswordEvent>(postOnlineMultipleTimePassword);
|
on<OnlineMultipleTimePasswordEvent>(postOnlineMultipleTimePassword);
|
||||||
@ -39,6 +40,8 @@ class VisitorPasswordBloc
|
|||||||
final TextEditingController unitNameController = TextEditingController();
|
final TextEditingController unitNameController = TextEditingController();
|
||||||
final TextEditingController virtualAddressController = TextEditingController();
|
final TextEditingController virtualAddressController = TextEditingController();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
List<DeviceModel> data = [];
|
List<DeviceModel> data = [];
|
||||||
List<String> selectedDeviceIds = [];
|
List<String> selectedDeviceIds = [];
|
||||||
|
|
||||||
@ -55,11 +58,18 @@ class VisitorPasswordBloc
|
|||||||
int? effectiveTimeTimeStamp;
|
int? effectiveTimeTimeStamp;
|
||||||
int? expirationTimeTimeStamp;
|
int? expirationTimeTimeStamp;
|
||||||
|
|
||||||
|
int? repeatEffectiveTimeTimeStamp;
|
||||||
|
int? repeatExpirationTimeTimeStamp;
|
||||||
|
|
||||||
String startTime = 'Start Time';
|
String startTime = 'Start Time';
|
||||||
String endTime = 'End Time';
|
String endTime = 'End Time';
|
||||||
|
|
||||||
DateTime? repeatStartTime=DateTime.now();
|
|
||||||
DateTime? repeatEndTime;
|
String repeatStartTime = 'Start Time';
|
||||||
|
String repeatEndTime = 'End Time';
|
||||||
|
|
||||||
|
// DateTime? repeatStartTime=DateTime.now();
|
||||||
|
// DateTime? repeatEndTime;
|
||||||
|
|
||||||
selectAccessType(
|
selectAccessType(
|
||||||
SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
|
SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
|
||||||
@ -80,7 +90,7 @@ class VisitorPasswordBloc
|
|||||||
context: event.context,
|
context: event.context,
|
||||||
initialDate: DateTime.now(),
|
initialDate: DateTime.now(),
|
||||||
firstDate: DateTime(2015, 8),
|
firstDate: DateTime(2015, 8),
|
||||||
lastDate: DateTime(2101),
|
lastDate: DateTime(3101),
|
||||||
);
|
);
|
||||||
if (picked != null) {
|
if (picked != null) {
|
||||||
final TimeOfDay? timePicked = await showTimePicker(
|
final TimeOfDay? timePicked = await showTimePicker(
|
||||||
@ -120,33 +130,34 @@ class VisitorPasswordBloc
|
|||||||
).millisecondsSinceEpoch ~/
|
).millisecondsSinceEpoch ~/
|
||||||
1000; // Divide by 1000 to remove milliseconds
|
1000; // Divide by 1000 to remove milliseconds
|
||||||
if (event.isStart) {
|
if (event.isStart) {
|
||||||
if (expirationTimeTimeStamp != null &&
|
if (expirationTimeTimeStamp != null && selectedTimestamp >expirationTimeTimeStamp!) {
|
||||||
selectedTimestamp > expirationTimeTimeStamp!) {
|
CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.');
|
||||||
CustomSnackBar.displaySnackBar(
|
|
||||||
'Effective Time cannot be later than Expiration Time.');
|
|
||||||
} else {
|
} else {
|
||||||
startTime = selectedDateTime
|
if(event.isRepeat==true)
|
||||||
.toString()
|
{repeatStartTime = selectedDateTime.toString().split('.').first;}
|
||||||
.split('.')
|
|
||||||
.first; // Remove seconds and milliseconds
|
else // Remove seconds and milliseconds
|
||||||
|
{startTime = selectedDateTime.toString().split('.').first;}
|
||||||
effectiveTimeTimeStamp = selectedTimestamp;
|
effectiveTimeTimeStamp = selectedTimestamp;
|
||||||
|
emit(ChangeTimeState());
|
||||||
}
|
}
|
||||||
emit(ChangeTimeState());
|
emit(ChangeTimeState());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (effectiveTimeTimeStamp != null &&
|
if (effectiveTimeTimeStamp != null &&
|
||||||
selectedTimestamp < effectiveTimeTimeStamp!) {
|
selectedTimestamp < effectiveTimeTimeStamp!) {
|
||||||
CustomSnackBar.displaySnackBar(
|
CustomSnackBar.displaySnackBar('Expiration Time cannot be earlier than Effective Time.');
|
||||||
'Expiration Time cannot be earlier than Effective Time.');
|
|
||||||
} else {
|
} else {
|
||||||
endTime = selectedDateTime
|
if(event.isRepeat==true)
|
||||||
.toString()
|
{repeatEndTime = selectedDateTime.toString().split('.').first;}
|
||||||
.split('.')
|
else
|
||||||
.first; // Remove seconds and milliseconds
|
{endTime = selectedDateTime.toString().split('.').first;}
|
||||||
expirationTimeTimeStamp = selectedTimestamp;
|
expirationTimeTimeStamp = selectedTimestamp;
|
||||||
}
|
emit(ChangeTimeState());
|
||||||
emit(VisitorPasswordInitial());
|
|
||||||
|
|
||||||
|
}
|
||||||
|
emit(ChangeTimeState());
|
||||||
|
|
||||||
|
emit(VisitorPasswordInitial());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,12 +236,12 @@ class VisitorPasswordBloc
|
|||||||
// emit(DeviceLoaded());
|
// emit(DeviceLoaded());
|
||||||
await AccessMangApi().postOnlineMultipleTime(
|
await AccessMangApi().postOnlineMultipleTime(
|
||||||
scheduleList:[
|
scheduleList:[
|
||||||
if (repeat)
|
// if (repeat)
|
||||||
Schedule(
|
// Schedule(
|
||||||
effectiveTime: getTimeOnly(repeatStartTime),
|
// effectiveTime: getTimeOnly(repeatStartTime),
|
||||||
invalidTime: getTimeOnly(repeatEndTime).toString(),
|
// invalidTime: getTimeOnly(repeatEndTime).toString(),
|
||||||
workingDay: selectedDays,
|
// workingDay: selectedDays,
|
||||||
),
|
// ),
|
||||||
] ,
|
] ,
|
||||||
password: passwordController,
|
password: passwordController,
|
||||||
invalidTime:event.invalidTime ,
|
invalidTime:event.invalidTime ,
|
||||||
@ -297,7 +308,7 @@ class VisitorPasswordBloc
|
|||||||
|
|
||||||
String? validate(String? value) {
|
String? validate(String? value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Field is required';
|
return '';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -317,4 +328,34 @@ class VisitorPasswordBloc
|
|||||||
if (dateTime == null) return '';
|
if (dateTime == null) return '';
|
||||||
return DateFormat('HH:mm').format(dateTime);
|
return DateFormat('HH:mm').format(dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void filterDevices() {
|
||||||
|
final deviceName = deviceNameController.text.toLowerCase();
|
||||||
|
final deviceId = deviceIdController.text.toLowerCase();
|
||||||
|
final unitName = unitNameController.text.toLowerCase();
|
||||||
|
|
||||||
|
final filteredData = data.where((device) {
|
||||||
|
final matchesDeviceName = device.name.toLowerCase().contains(deviceName);
|
||||||
|
final matchesDeviceId = device.uuid.toLowerCase().contains(deviceId);
|
||||||
|
// final matchesUnitName = device.unitName.toLowerCase().contains(unitName); // Assuming unitName is a property of the device
|
||||||
|
|
||||||
|
return matchesDeviceName && matchesDeviceId ;
|
||||||
|
}).toList();
|
||||||
|
// emit(TableLoaded(filteredData));
|
||||||
|
|
||||||
|
add(UpdateFilteredDevicesEvent(filteredData));
|
||||||
|
}
|
||||||
|
@override
|
||||||
|
Stream<VisitorPasswordState> mapEventToState(VisitorPasswordEvent event) async* {
|
||||||
|
if (event is FetchDevice) {
|
||||||
|
// Fetching logic...
|
||||||
|
} else if (event is UpdateFilteredDevicesEvent) {
|
||||||
|
yield TableLoaded(event.filteredData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onUpdateFilteredDevices(UpdateFilteredDevicesEvent event, Emitter<VisitorPasswordState> emit) {
|
||||||
|
emit(TableLoaded(event.filteredData));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
||||||
|
|
||||||
abstract class VisitorPasswordEvent extends Equatable {
|
abstract class VisitorPasswordEvent extends Equatable {
|
||||||
const VisitorPasswordEvent();
|
const VisitorPasswordEvent();
|
||||||
@ -28,11 +29,12 @@ class SelectUsageFrequency extends VisitorPasswordEvent {
|
|||||||
class SelectTimeVisitorPassword extends VisitorPasswordEvent {
|
class SelectTimeVisitorPassword extends VisitorPasswordEvent {
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
final bool isStart;
|
final bool isStart;
|
||||||
|
final bool isRepeat;
|
||||||
|
|
||||||
const SelectTimeVisitorPassword({ required this.context,required this.isStart});
|
const SelectTimeVisitorPassword({ required this.context,required this.isStart,required this.isRepeat});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [context,isStart];
|
List<Object> get props => [context,isStart,isRepeat];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -97,3 +99,20 @@ class SelectDeviceEvent extends VisitorPasswordEvent {
|
|||||||
final String deviceId;
|
final String deviceId;
|
||||||
const SelectDeviceEvent(this.deviceId);
|
const SelectDeviceEvent(this.deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FilterDataEvent extends VisitorPasswordEvent {
|
||||||
|
final String? passwordName;
|
||||||
|
final int? startTime;
|
||||||
|
final int? endTime;
|
||||||
|
|
||||||
|
const FilterDataEvent({
|
||||||
|
this.passwordName,
|
||||||
|
this.startTime,
|
||||||
|
this.endTime,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
class UpdateFilteredDevicesEvent extends VisitorPasswordEvent {
|
||||||
|
final List<DeviceModel> filteredData;
|
||||||
|
|
||||||
|
UpdateFilteredDevicesEvent(this.filteredData);
|
||||||
|
}
|
@ -16,9 +16,7 @@ class VisitorPasswordInitial extends VisitorPasswordState {}
|
|||||||
|
|
||||||
class PasswordTypeSelected extends VisitorPasswordState {
|
class PasswordTypeSelected extends VisitorPasswordState {
|
||||||
final String selectedType;
|
final String selectedType;
|
||||||
|
|
||||||
const PasswordTypeSelected(this.selectedType);
|
const PasswordTypeSelected(this.selectedType);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [selectedType];
|
List<Object> get props => [selectedType];
|
||||||
}
|
}
|
||||||
@ -45,19 +43,17 @@ class LoadingInitialState extends VisitorPasswordState {}
|
|||||||
class ChangeTimeState extends VisitorPasswordState {}
|
class ChangeTimeState extends VisitorPasswordState {}
|
||||||
class DeviceLoaded extends VisitorPasswordState {}
|
class DeviceLoaded extends VisitorPasswordState {}
|
||||||
class GeneratePasswordState extends VisitorPasswordState {}
|
class GeneratePasswordState extends VisitorPasswordState {}
|
||||||
|
|
||||||
class FailedState extends VisitorPasswordState {
|
class FailedState extends VisitorPasswordState {
|
||||||
final String message;
|
final String message;
|
||||||
|
const FailedState(this.message);
|
||||||
FailedState(this.message);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
}
|
}
|
||||||
|
|
||||||
class TableLoaded extends VisitorPasswordState {
|
class TableLoaded extends VisitorPasswordState {
|
||||||
final List<DeviceModel> data;
|
final List<DeviceModel> data;
|
||||||
|
|
||||||
const TableLoaded(this.data);
|
const TableLoaded(this.data);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [data];
|
List<Object> get props => [data];
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'package:syncrow_web/utils/constants/const.dart';
|
||||||
|
|
||||||
class DeviceModel {
|
class DeviceModel {
|
||||||
dynamic productUuid;
|
dynamic productUuid;
|
||||||
dynamic productType;
|
dynamic productType;
|
||||||
@ -15,7 +17,7 @@ class DeviceModel {
|
|||||||
dynamic lon;
|
dynamic lon;
|
||||||
dynamic model;
|
dynamic model;
|
||||||
dynamic name;
|
dynamic name;
|
||||||
dynamic online;
|
DeviseStatus online;
|
||||||
dynamic ownerId;
|
dynamic ownerId;
|
||||||
dynamic sub;
|
dynamic sub;
|
||||||
dynamic timeZone;
|
dynamic timeZone;
|
||||||
@ -62,7 +64,7 @@ class DeviceModel {
|
|||||||
lon: json['lon'] ,
|
lon: json['lon'] ,
|
||||||
model: json['model'] ,
|
model: json['model'] ,
|
||||||
name: json['name'],
|
name: json['name'],
|
||||||
online: json['online'],
|
online: OnlineTypeExtension.fromString(json['online']),
|
||||||
ownerId: json['ownerId'] ,
|
ownerId: json['ownerId'] ,
|
||||||
sub: json['sub'],
|
sub: json['sub'],
|
||||||
timeZone: json['timeZone'],
|
timeZone: json['timeZone'],
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
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/flutter_svg.dart';
|
||||||
@ -10,6 +9,7 @@ import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.d
|
|||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.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/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/const.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
|
|
||||||
@ -34,13 +34,13 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Container(
|
Container(
|
||||||
width: size.width,
|
width: size.width,
|
||||||
padding: EdgeInsets.all(15),
|
padding: EdgeInsets.all(15),
|
||||||
decoration:containerDecoration.copyWith(
|
decoration:containerDecoration.copyWith(
|
||||||
color: ColorsManager.worningColor,
|
color: ColorsManager.worningColor,
|
||||||
border: Border.all(color: Color(0xffFFD22F)),
|
border: Border.all(color: Color(0xffFFD22F)),
|
||||||
boxShadow: []
|
boxShadow: []
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@ -73,7 +73,7 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: CustomWebTextField(
|
child: CustomWebTextField(
|
||||||
controller: visitorBloc.deviceNameController,
|
controller: visitorBloc.deviceIdController,
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
textFieldName: 'Device ID',
|
textFieldName: 'Device ID',
|
||||||
description: '',
|
description: '',
|
||||||
@ -103,7 +103,7 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// Your search function here
|
visitorBloc.filterDevices(); // Call filter function
|
||||||
},
|
},
|
||||||
borderRadius: 9,
|
borderRadius: 9,
|
||||||
child: const Text('Search'),
|
child: const Text('Search'),
|
||||||
@ -133,6 +133,12 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
'Reset',
|
'Reset',
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),
|
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
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -145,7 +151,7 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: state is TableLoaded
|
child: state is TableLoaded
|
||||||
? Container(
|
? Container(
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
child: DynamicTable(
|
child: DynamicTable(
|
||||||
selectAll: (p0) {
|
selectAll: (p0) {
|
||||||
@ -160,14 +166,14 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
withCheckBox: true,
|
withCheckBox: true,
|
||||||
size: size*0.5,
|
size: size*0.5,
|
||||||
headers: const [ 'Device Name', 'Device ID', 'Access Type', 'Unit Name', 'Status'],
|
headers: const [ 'Device Name', 'Device ID', 'Access Type', 'Unit Name', 'Status'],
|
||||||
data: state.data.map((item) {
|
data: state.data.map((item) {
|
||||||
return [
|
return [
|
||||||
item.name.toString(),
|
item.name.toString(),
|
||||||
item.uuid.toString(),
|
item.uuid.toString(),
|
||||||
item.productType.toString(),
|
item.productType.toString(),
|
||||||
'',
|
'',
|
||||||
item.online.toString(),
|
item.online.value.toString(),
|
||||||
];
|
];
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
@ -195,13 +201,11 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
|
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
width: size.width * 0.2,
|
width: size.width * 0.2,
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop(); // Close the dialog
|
Navigator.of(context).pop(); // Close the dialog
|
||||||
|
|
||||||
},
|
},
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
child: Text('Ok'),
|
child: Text('Ok'),
|
||||||
@ -211,5 +215,6 @@ class AddDeviceDialog extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
); }
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,29 +20,6 @@ class RepeatWidget extends StatelessWidget {
|
|||||||
final smartDoorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
final smartDoorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||||
return Column(
|
return Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: DateTimeWebWidget(
|
|
||||||
isRequired: true,
|
|
||||||
title: 'Access Period',
|
|
||||||
size: size,
|
|
||||||
endTime: () {
|
|
||||||
smartDoorBloc.add(SelectTimeVisitorPassword(context: context, isStart: false));
|
|
||||||
},
|
|
||||||
startTime: () {
|
|
||||||
smartDoorBloc.add(SelectTimeVisitorPassword(context: context, isStart: true));
|
|
||||||
},
|
|
||||||
firstString: smartDoorBloc.startTime,
|
|
||||||
secondString: smartDoorBloc.endTime,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(
|
|
||||||
color: ColorsManager.graysColor,
|
|
||||||
),
|
|
||||||
const Divider(
|
|
||||||
color: ColorsManager.graysColor,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
Container(
|
Container(
|
||||||
width: size.width * 0.8,
|
width: size.width * 0.8,
|
||||||
height: size.height * 0.06, // Adjust height as needed
|
height: size.height * 0.06, // Adjust height as needed
|
||||||
@ -72,6 +49,29 @@ class RepeatWidget extends StatelessWidget {
|
|||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: DateTimeWebWidget(
|
||||||
|
isRequired: false,
|
||||||
|
title: '',
|
||||||
|
size: size,
|
||||||
|
endTime: () {
|
||||||
|
smartDoorBloc.add(SelectTimeVisitorPassword(
|
||||||
|
isRepeat: true,
|
||||||
|
context: context, isStart: false
|
||||||
|
));
|
||||||
|
},
|
||||||
|
startTime: () {
|
||||||
|
smartDoorBloc.add(SelectTimeVisitorPassword(
|
||||||
|
isRepeat: true,
|
||||||
|
context: context, isStart: true
|
||||||
|
));
|
||||||
|
},
|
||||||
|
firstString: smartDoorBloc.repeatStartTime.toString(),
|
||||||
|
secondString: smartDoorBloc.repeatEndTime.toString(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
],
|
],
|
||||||
|
@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.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';
|
||||||
@ -79,7 +80,6 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: size.width * 0.15,
|
width: size.width * 0.15,
|
||||||
child: RadioListTile<String>(
|
child: RadioListTile<String>(
|
||||||
@ -90,6 +90,7 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
: visitorBloc.accessTypeSelected,
|
: visitorBloc.accessTypeSelected,
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
|
print(value);
|
||||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -106,6 +107,8 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
: visitorBloc.accessTypeSelected,
|
: visitorBloc.accessTypeSelected,
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
|
print(value);
|
||||||
|
|
||||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -123,6 +126,7 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
|
||||||
|
visitorBloc.usageFrequencySelected='';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -130,7 +134,7 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
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'),
|
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,)
|
const SizedBox(height: 20,)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
visitorBloc.accessTypeSelected=='Dynamic Password' ?
|
visitorBloc.accessTypeSelected=='Dynamic Password' ?
|
||||||
@ -162,6 +166,8 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
: visitorBloc.usageFrequencySelected,
|
: visitorBloc.usageFrequencySelected,
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
|
print(value);
|
||||||
|
|
||||||
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
|
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -185,27 +191,28 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
Text('Within the validity period, each device can be unlocked only once.')
|
const Text('Within the validity period, each device can be unlocked only once.')
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 20,),
|
const SizedBox(height: 20,),
|
||||||
|
if((visitorBloc.usageFrequencySelected!='One-Time'||visitorBloc.accessTypeSelected!='Offline Password')&&(visitorBloc.usageFrequencySelected!=''))
|
||||||
visitorBloc.accessTypeSelected=='Dynamic Password' ?
|
|
||||||
SizedBox():
|
|
||||||
DateTimeWebWidget(
|
DateTimeWebWidget(
|
||||||
|
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
title: 'Access Period',
|
title: 'Access Period',
|
||||||
size: size,
|
size: size,
|
||||||
endTime: () {
|
endTime: () {
|
||||||
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: false));
|
visitorBloc.add(SelectTimeVisitorPassword(
|
||||||
|
context: context, isStart: false,isRepeat:false));
|
||||||
},
|
},
|
||||||
startTime: () {
|
startTime: () {
|
||||||
visitorBloc.add(SelectTimeVisitorPassword(context: context, isStart: true));
|
visitorBloc.add(SelectTimeVisitorPassword(
|
||||||
|
context: context, isStart: true,isRepeat:false));
|
||||||
},
|
},
|
||||||
firstString: visitorBloc.startTime,
|
firstString: visitorBloc.startTime,
|
||||||
secondString: visitorBloc.endTime,
|
secondString: visitorBloc.endTime,
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 20,),
|
const SizedBox(height: 20,),
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
@ -243,7 +250,8 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
isRepeat ? const RepeatWidget() : const SizedBox(),
|
if(visitorBloc.usageFrequencySelected=='Periodic'&&visitorBloc.accessTypeSelected=='Online Password')
|
||||||
|
isRepeat ? const RepeatWidget() : const SizedBox(),
|
||||||
Container(
|
Container(
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
width: size.width * 0.1,
|
width: size.width * 0.1,
|
||||||
@ -254,7 +262,6 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return const AddDeviceDialog();
|
return const AddDeviceDialog();
|
||||||
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -293,39 +300,79 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if(visitorBloc.forgetFormKey.currentState!.validate()){
|
if(visitorBloc.forgetFormKey.currentState!.validate()){
|
||||||
if(visitorBloc.usageFrequencySelected=='One-Time'&&visitorBloc.accessTypeSelected=='Online Password'){
|
showDialog(
|
||||||
visitorBloc.add(OnlineOneTimePasswordEvent(
|
context: context,
|
||||||
passwordName:visitorBloc.userNameController.text ,
|
barrierDismissible: false,
|
||||||
email: visitorBloc.emailController.text
|
builder: (BuildContext context) {
|
||||||
)
|
return InfoDialog(
|
||||||
);
|
size: size,
|
||||||
}else if(visitorBloc.usageFrequencySelected=='Periodic'&&visitorBloc.accessTypeSelected=='Online Password') {
|
title: 'Set Password',
|
||||||
visitorBloc.add(OnlineMultipleTimePasswordEvent(
|
content: 'This action will update all of the selected\n door locks passwords in the property.\n\nAre you sure you want to continue?',
|
||||||
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()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
actions: [
|
||||||
|
Container(
|
||||||
|
decoration: containerDecoration,
|
||||||
|
width: size.width * 0.1,
|
||||||
|
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.1,
|
||||||
|
child: DefaultButton(
|
||||||
|
borderRadius: 8,
|
||||||
|
onPressed: () {
|
||||||
|
if(visitorBloc.usageFrequencySelected=='One-Time'&&visitorBloc.accessTypeSelected=='Online Password'){
|
||||||
|
visitorBloc.add(OnlineOneTimePasswordEvent(
|
||||||
|
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: const Text(
|
||||||
|
'Ok',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
child: Text('Ok'),
|
child: Text('Ok'),
|
||||||
|
@ -42,3 +42,38 @@ extension AccessTypeExtension on AccessType {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enum DeviseStatus {
|
||||||
|
online,
|
||||||
|
offline,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension OnlineTypeExtension on DeviseStatus {
|
||||||
|
String get value {
|
||||||
|
switch (this) {
|
||||||
|
case DeviseStatus.online:
|
||||||
|
return "Online";
|
||||||
|
case DeviseStatus.offline:
|
||||||
|
return "Offline";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DeviseStatus fromString(bool value) {
|
||||||
|
switch (value) {
|
||||||
|
case false:
|
||||||
|
return DeviseStatus.offline;
|
||||||
|
case true:
|
||||||
|
return DeviseStatus.online;
|
||||||
|
default:
|
||||||
|
throw ArgumentError("Invalid access type: $value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user