mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
fix bugs
This commit is contained in:
@ -6,6 +6,7 @@ import 'package:syncrow_web/pages/auth/view/login_page.dart';
|
|||||||
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
|
import 'package:syncrow_web/pages/home/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/bloc/visitor_password_bloc.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';
|
||||||
|
|
||||||
@ -56,10 +57,10 @@ class MyApp extends StatelessWidget {
|
|||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
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:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
|
home:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -81,34 +81,12 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
lastDate: DateTime(2101),
|
lastDate: DateTime(2101),
|
||||||
);
|
);
|
||||||
if (picked != null) {
|
if (picked != null) {
|
||||||
final TimeOfDay? timePicked = await showTimePicker(
|
|
||||||
context: event.context,
|
|
||||||
initialTime: TimeOfDay.now(),
|
|
||||||
|
|
||||||
builder: (context, child) {
|
|
||||||
return Theme(
|
|
||||||
data: ThemeData.light().copyWith(
|
|
||||||
colorScheme: const ColorScheme.light(
|
|
||||||
primary: ColorsManager.primaryColor,
|
|
||||||
onSurface: Colors.black,
|
|
||||||
),
|
|
||||||
buttonTheme: const ButtonThemeData(
|
|
||||||
colorScheme: ColorScheme.light(
|
|
||||||
primary: Colors.green,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: child!,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (timePicked != null) {
|
|
||||||
final selectedDateTime = DateTime(
|
final selectedDateTime = DateTime(
|
||||||
picked.year,
|
picked.year,
|
||||||
picked.month,
|
picked.month,
|
||||||
picked.day,
|
picked.day,
|
||||||
timePicked.hour,
|
|
||||||
timePicked.minute,
|
|
||||||
);
|
);
|
||||||
final selectedTimestamp = DateTime(
|
final selectedTimestamp = DateTime(
|
||||||
selectedDateTime.year,
|
selectedDateTime.year,
|
||||||
@ -132,17 +110,23 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
expirationTimeTimeStamp = selectedTimestamp;
|
expirationTimeTimeStamp = selectedTimestamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
emit(ChangeTimeState());
|
emit(ChangeTimeState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
|
Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
try {
|
try {
|
||||||
filteredData = data.where((item) {
|
filteredData = data.where((item) {
|
||||||
bool matchesCriteria = true;
|
bool matchesCriteria = true;
|
||||||
|
|
||||||
|
// Convert timestamp to DateTime and extract date component
|
||||||
|
DateTime effectiveDate = DateTime.fromMillisecondsSinceEpoch(int.parse(item.effectiveTime.toString()) * 1000).toUtc().toLocal();
|
||||||
|
DateTime invalidDate = DateTime.fromMillisecondsSinceEpoch(int.parse(item.invalidTime.toString()) * 1000).toUtc().toLocal();
|
||||||
|
DateTime effectiveDateOnly = DateTime(effectiveDate.year, effectiveDate.month, effectiveDate.day);
|
||||||
|
DateTime invalidDateOnly = DateTime(invalidDate.year, invalidDate.month, invalidDate.day);
|
||||||
|
|
||||||
|
// Filter by password name
|
||||||
if (event.passwordName != null && event.passwordName!.isNotEmpty) {
|
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);
|
||||||
@ -150,19 +134,37 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
matchesCriteria = false;
|
matchesCriteria = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter by start date only
|
||||||
|
if (event.startTime != null && event.endTime == null) {
|
||||||
|
DateTime startDateOnly = DateTime.fromMillisecondsSinceEpoch(event.startTime! * 1000).toUtc().toLocal();
|
||||||
|
startDateOnly = DateTime(startDateOnly.year, startDateOnly.month, startDateOnly.day);
|
||||||
|
if (effectiveDateOnly.isBefore(startDateOnly)) {
|
||||||
|
matchesCriteria = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by end date only
|
||||||
|
if (event.endTime != null && event.startTime == null) {
|
||||||
|
DateTime endDateOnly = DateTime.fromMillisecondsSinceEpoch(event.endTime! * 1000).toUtc().toLocal();
|
||||||
|
endDateOnly = DateTime(endDateOnly.year, endDateOnly.month, endDateOnly.day);
|
||||||
|
if (invalidDateOnly.isAfter(endDateOnly)) {
|
||||||
|
matchesCriteria = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter by both start date and end date
|
||||||
if (event.startTime != null && event.endTime != null) {
|
if (event.startTime != null && event.endTime != null) {
|
||||||
final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
|
DateTime startDateOnly = DateTime.fromMillisecondsSinceEpoch(event.startTime! * 1000).toUtc().toLocal();
|
||||||
final int? invalidTime = int.tryParse(item.invalidTime.toString());
|
DateTime endDateOnly = DateTime.fromMillisecondsSinceEpoch(event.endTime! * 1000).toUtc().toLocal();
|
||||||
if (effectiveTime == null || invalidTime == null) {
|
startDateOnly = DateTime(startDateOnly.year, startDateOnly.month, startDateOnly.day);
|
||||||
matchesCriteria = false;
|
endDateOnly = DateTime(endDateOnly.year, endDateOnly.month, endDateOnly.day);
|
||||||
} else {
|
if (effectiveDateOnly.isBefore(startDateOnly) || invalidDateOnly.isAfter(endDateOnly)) {
|
||||||
final bool matchesStartTime = effectiveTime >= event.startTime!;
|
|
||||||
final bool matchesEndTime = invalidTime <= event.endTime!;
|
|
||||||
if (!matchesStartTime || !matchesEndTime) {
|
|
||||||
matchesCriteria = false;
|
matchesCriteria = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// Filter by selected tab index
|
||||||
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') {
|
||||||
@ -170,14 +172,122 @@ 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));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
|
||||||
|
// emit(AccessLoaded());
|
||||||
|
// try {
|
||||||
|
// filteredData = data.where((item) {
|
||||||
|
// bool matchesCriteria = true;
|
||||||
|
//
|
||||||
|
// // Filter by password name
|
||||||
|
// if (event.passwordName != null && event.passwordName!.isNotEmpty) {
|
||||||
|
// final bool matchesName = item.passwordName != null &&
|
||||||
|
// item.passwordName.contains(event.passwordName);
|
||||||
|
// if (!matchesName) {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Filter by start time only
|
||||||
|
// if (event.startTime != null && event.endTime == null) {
|
||||||
|
// final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
|
||||||
|
// if (effectiveTime == null || effectiveTime < event.startTime!) {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Filter by end time only
|
||||||
|
// if (event.endTime != null && event.startTime == null) {
|
||||||
|
// final int? invalidTime = int.tryParse(item.invalidTime.toString());
|
||||||
|
// if (invalidTime == null || invalidTime > event.endTime!) {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Filter by both start time and end time
|
||||||
|
// if (event.startTime != null && event.endTime != null) {
|
||||||
|
// final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
|
||||||
|
// final int? invalidTime = int.tryParse(item.invalidTime.toString());
|
||||||
|
// if (effectiveTime == null || invalidTime == null) {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// } else {
|
||||||
|
// final bool matchesStartTime = effectiveTime >= event.startTime!;
|
||||||
|
// final bool matchesEndTime = invalidTime <= event.endTime!;
|
||||||
|
// if (!matchesStartTime || !matchesEndTime) {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Filter by selected tab index
|
||||||
|
// if (event.selectedTabIndex == 1 && item.passwordStatus.value != 'To Be Effective') {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// } else if (event.selectedTabIndex == 2 && item.passwordStatus.value != 'Effective') {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// } else if (event.selectedTabIndex == 3 && item.passwordStatus.value != 'Expired') {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return matchesCriteria;
|
||||||
|
// }).toList();
|
||||||
|
//
|
||||||
|
// emit(TableLoaded(filteredData));
|
||||||
|
// } catch (e) {
|
||||||
|
// emit(FailedState(e.toString()));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
|
||||||
|
// emit(AccessLoaded());
|
||||||
|
// try {
|
||||||
|
// filteredData = data.where((item) {
|
||||||
|
// bool matchesCriteria = true;
|
||||||
|
// if (event.passwordName != null && event.passwordName!.isNotEmpty) {
|
||||||
|
// final bool matchesName = item.passwordName != null &&
|
||||||
|
// item.passwordName.contains(event.passwordName);
|
||||||
|
// if (!matchesName) {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (event.startTime != null || event.endTime != null) {
|
||||||
|
// final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
|
||||||
|
// final int? invalidTime = int.tryParse(item.invalidTime.toString());
|
||||||
|
// if (effectiveTime == null || invalidTime == null) {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// } else {
|
||||||
|
// final bool matchesStartTime = effectiveTime >= event.startTime!;
|
||||||
|
// final bool matchesEndTime = invalidTime <= event.endTime!;
|
||||||
|
// if (!matchesStartTime || !matchesEndTime) {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (event.selectedTabIndex == 1 && item.passwordStatus.value != 'To Be Effective') {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// } else if (event.selectedTabIndex == 2 && item.passwordStatus.value != 'Effective') {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// } else if (event.selectedTabIndex == 3 && item.passwordStatus.value != 'Expired') {
|
||||||
|
// matchesCriteria = false;
|
||||||
|
// }
|
||||||
|
// return matchesCriteria;
|
||||||
|
// }).toList();
|
||||||
|
// emit(TableLoaded(filteredData));
|
||||||
|
// } catch (e) {
|
||||||
|
// emit(FailedState(e.toString()));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
resetSearch(ResetSearch event, Emitter<AccessState> emit) async{
|
resetSearch(ResetSearch event, Emitter<AccessState> emit) async{
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
startTime = 'Start Time';
|
startTime = 'Start Time';
|
||||||
|
@ -4,6 +4,7 @@ import 'package:syncrow_web/pages/access_management/bloc/access_bloc.dart';
|
|||||||
import 'package:syncrow_web/pages/access_management/bloc/access_event.dart';
|
import 'package:syncrow_web/pages/access_management/bloc/access_event.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/bloc/access_state.dart';
|
import 'package:syncrow_web/pages/access_management/bloc/access_state.dart';
|
||||||
import 'package:syncrow_web/pages/common/custom_table.dart';
|
import 'package:syncrow_web/pages/common/custom_table.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/custom_web_textfield.dart';
|
||||||
import 'package:syncrow_web/pages/common/date_time_widget.dart';
|
import 'package:syncrow_web/pages/common/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/visitor_password/view/visitor_password_dialog.dart';
|
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
|
||||||
@ -101,26 +102,14 @@ class AccessManagementPage extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
textBaseline: TextBaseline.ideographic, children: [
|
textBaseline: TextBaseline.ideographic, children: [
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text('Name',
|
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
|
||||||
color: Colors.black,fontSize: 13),),
|
|
||||||
const SizedBox(height: 5,),
|
|
||||||
Container(
|
Container(
|
||||||
height:43,
|
|
||||||
width: size.width * 0.15,
|
width: size.width * 0.15,
|
||||||
decoration: containerDecoration,
|
child: CustomWebTextField(
|
||||||
child: TextFormField(
|
|
||||||
controller: accessBloc.passwordName,
|
controller: accessBloc.passwordName,
|
||||||
style: const TextStyle(color: Colors.black),
|
isRequired: true,
|
||||||
decoration: textBoxDecoration()!
|
textFieldName: 'Name',
|
||||||
.copyWith(hintText: 'Please enter'),
|
description: '',
|
||||||
)
|
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 15,
|
width: 15,
|
||||||
|
@ -7,6 +7,7 @@ Future<void> showCustomDialog({
|
|||||||
required String message,
|
required String message,
|
||||||
String? title,
|
String? title,
|
||||||
String? iconPath,
|
String? iconPath,
|
||||||
|
Widget? widget,
|
||||||
double? dialogHeight,
|
double? dialogHeight,
|
||||||
double? iconHeight,
|
double? iconHeight,
|
||||||
double? iconWidth,
|
double? iconWidth,
|
||||||
@ -53,6 +54,8 @@ Future<void> showCustomDialog({
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if(widget!=null)
|
||||||
|
Expanded(child:widget)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -73,7 +73,7 @@ class CustomWebTextField extends StatelessWidget {
|
|||||||
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
|
||||||
|
hintStyle: TextStyle(color: ColorsManager.grayColor),
|
||||||
hintText: 'Please enter'),
|
hintText: 'Please enter'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -49,7 +49,7 @@ class DateTimeWebWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 8,),
|
const SizedBox(height: 8,),
|
||||||
Container(
|
Container(
|
||||||
height:size.height * 0.055 ,
|
height:50 ,
|
||||||
padding: EdgeInsets.only(top: 10,bottom: 10,right: 30,left: 10),
|
padding: EdgeInsets.only(top: 10,bottom: 10,right: 30,left: 10),
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
@ -69,7 +69,6 @@ class DateTimeWebWidget extends StatelessWidget {
|
|||||||
SizedBox(width: 30,),
|
SizedBox(width: 30,),
|
||||||
const Icon(Icons.arrow_right_alt),
|
const Icon(Icons.arrow_right_alt),
|
||||||
SizedBox(width: 30,),
|
SizedBox(width: 30,),
|
||||||
|
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap:endTime,
|
onTap:endTime,
|
||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
|
@ -18,16 +18,25 @@ class HomeCard extends StatelessWidget {
|
|||||||
});
|
});
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool evenNumbers = index % 2 == 0;
|
// bool evenNumbers = index % 2 == 0;
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: active ? onTap : null,
|
onTap: active ? onTap : null,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.only(left: 10,right: 10,bottom: 10),
|
padding: const EdgeInsets.only(left: 10,right: 10,bottom: 10),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: evenNumbers && active?
|
color: index==0&&active?
|
||||||
ColorsManager.blueColor.withOpacity(0.8) :
|
ColorsManager.blue1.withOpacity(0.9):
|
||||||
(active ?ColorsManager.blueColor
|
index==1&&active?
|
||||||
: ColorsManager.blueColor.withOpacity(0.2)),
|
ColorsManager.blue2.withOpacity(0.9) :
|
||||||
|
index==2&&active?
|
||||||
|
ColorsManager.blue3:
|
||||||
|
index==4&&active==false?
|
||||||
|
ColorsManager.blue4.withOpacity(0.2):
|
||||||
|
index==7&&active==false?
|
||||||
|
ColorsManager.blue4.withOpacity(0.2):
|
||||||
|
ColorsManager.blueColor.withOpacity(0.2),
|
||||||
|
// (active ?ColorsManager.blueColor
|
||||||
|
// : ColorsManager.blueColor.withOpacity(0.2)),
|
||||||
borderRadius: BorderRadius.circular(30),
|
borderRadius: BorderRadius.circular(30),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
import 'package:dio/dio.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:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
@ -7,6 +8,7 @@ import 'package:syncrow_web/pages/common/hour_picker_dialog.dart';
|
|||||||
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
|
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_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';
|
||||||
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/visitor_password/model/failed_operation.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/model/schedule_model.dart';
|
import 'package:syncrow_web/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';
|
||||||
@ -62,7 +64,7 @@ class VisitorPasswordBloc
|
|||||||
|
|
||||||
String startTimeAccess = 'Start Time';
|
String startTimeAccess = 'Start Time';
|
||||||
String endTimeAccess = 'End Time';
|
String endTimeAccess = 'End Time';
|
||||||
|
PasswordStatus? passwordStatus;
|
||||||
selectAccessType(
|
selectAccessType(
|
||||||
SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
|
SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
|
||||||
accessTypeSelected = event.type;
|
accessTypeSelected = event.type;
|
||||||
@ -197,26 +199,23 @@ class VisitorPasswordBloc
|
|||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
generate7DigitNumber();
|
generate7DigitNumber();
|
||||||
bool res = await AccessMangApi().postOnlineOneTime(
|
var res = await AccessMangApi().postOnlineOneTime(
|
||||||
email: event.email,
|
email: event.email,
|
||||||
password: passwordController,
|
password: passwordController,
|
||||||
devicesUuid: selectedDevices,
|
devicesUuid: selectedDevices,
|
||||||
passwordName: event.passwordName,
|
passwordName: event.passwordName,
|
||||||
effectiveTime: effectiveTimeTimeStamp.toString(),
|
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||||
invalidTime: expirationTimeTimeStamp.toString());
|
invalidTime: expirationTimeTimeStamp.toString());
|
||||||
if (res == true) {
|
if(res['statusCode']==201){
|
||||||
|
passwordStatus= PasswordStatus.fromJson(res['data']);
|
||||||
emit(SuccessState());
|
emit(SuccessState());
|
||||||
} else {
|
|
||||||
throw Exception('Failed to create password');
|
|
||||||
}
|
}
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
} catch (e) {
|
} on DioException catch (e){
|
||||||
emit(FailedState(e.toString()));
|
final errorData = e.response!.data;
|
||||||
Navigator.pop(event.context!);
|
String errorMessage = errorData['message'];
|
||||||
stateDialog(
|
print('errorMessage==$errorData');
|
||||||
context: event.context!,
|
emit(FailedState(errorMessage.toString()));
|
||||||
message: e.toString(),
|
|
||||||
title: 'Something Wrong');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,13 +227,12 @@ class VisitorPasswordBloc
|
|||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
|
|
||||||
await generate7DigitNumber();
|
await generate7DigitNumber();
|
||||||
bool res = await AccessMangApi().postOnlineMultipleTime(
|
var res = await AccessMangApi().postOnlineMultipleTime(
|
||||||
scheduleList: [
|
scheduleList: [
|
||||||
if (repeat)
|
if (repeat)
|
||||||
Schedule(
|
Schedule(
|
||||||
effectiveTime: getTimeFromDateTimeString(expirationTime),
|
effectiveTime: getTimeFromDateTimeString(expirationTime),
|
||||||
invalidTime:
|
invalidTime: getTimeFromDateTimeString(effectiveTime).toString(),
|
||||||
getTimeFromDateTimeString(effectiveTime).toString(),
|
|
||||||
workingDay: selectedDays,
|
workingDay: selectedDays,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -244,47 +242,42 @@ class VisitorPasswordBloc
|
|||||||
email: event.email,
|
email: event.email,
|
||||||
devicesUuid: selectedDevices,
|
devicesUuid: selectedDevices,
|
||||||
passwordName: event.passwordName);
|
passwordName: event.passwordName);
|
||||||
if (res == true) {
|
if(res['statusCode']==201){
|
||||||
|
passwordStatus= PasswordStatus.fromJson(res['data']);
|
||||||
emit(SuccessState());
|
emit(SuccessState());
|
||||||
}else {
|
|
||||||
throw Exception('Failed to create password');
|
|
||||||
}
|
}
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
|
|
||||||
} catch (e) {
|
} on DioException catch (e){
|
||||||
emit(FailedState(e.toString()));
|
final errorData = e.response!.data;
|
||||||
Navigator.pop(event.context!);
|
String errorMessage = errorData['message'];
|
||||||
stateDialog(
|
print('errorMessage==$errorData');
|
||||||
context: event.context!,
|
emit(FailedState(errorMessage.toString()));
|
||||||
message: e.toString(),
|
|
||||||
title: 'Something Wrong');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//offline password
|
//offline password
|
||||||
Future<void> postOfflineOneTimePassword(OfflineOneTimePasswordEvent event,
|
Future<void> postOfflineOneTimePassword(
|
||||||
|
OfflineOneTimePasswordEvent event,
|
||||||
Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
await generate7DigitNumber();
|
await generate7DigitNumber();
|
||||||
bool res = await AccessMangApi().postOffLineOneTime(
|
var res = await AccessMangApi().postOffLineOneTime(
|
||||||
email: event.email,
|
email: event.email,
|
||||||
devicesUuid: selectedDevices,
|
devicesUuid: selectedDevices,
|
||||||
passwordName: event.passwordName);
|
passwordName: event.passwordName);
|
||||||
if (res == true) {
|
if(res['statusCode']==201){
|
||||||
|
passwordStatus= PasswordStatus.fromJson(res['data']);
|
||||||
emit(SuccessState());
|
emit(SuccessState());
|
||||||
}else {
|
|
||||||
throw Exception('Failed to create password');
|
|
||||||
}
|
}
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
|
|
||||||
} catch (e) {
|
} on DioException catch (e){
|
||||||
emit(FailedState(e.toString()));
|
final errorData = e.response!.data;
|
||||||
Navigator.pop(event.context!);
|
String errorMessage = errorData['message'];
|
||||||
stateDialog(
|
print('errorMessage==$errorData');
|
||||||
context: event.context!,
|
emit(FailedState(errorMessage.toString()));
|
||||||
message: e.toString(),
|
|
||||||
title: 'Something Wrong');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,27 +287,24 @@ class VisitorPasswordBloc
|
|||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
await generate7DigitNumber();
|
await generate7DigitNumber();
|
||||||
bool res = await AccessMangApi().postOffLineMultipleTime(
|
var res = await AccessMangApi().postOffLineMultipleTime(
|
||||||
email: event.email,
|
email: event.email,
|
||||||
devicesUuid: selectedDevices,
|
devicesUuid: selectedDevices,
|
||||||
passwordName: event.passwordName,
|
passwordName: event.passwordName,
|
||||||
invalidTime: expirationTimeTimeStamp.toString(),
|
invalidTime: expirationTimeTimeStamp.toString(),
|
||||||
effectiveTime: effectiveTimeTimeStamp.toString(),
|
effectiveTime: effectiveTimeTimeStamp.toString(),
|
||||||
);
|
);
|
||||||
if (res == true) {
|
if(res['statusCode']==201){
|
||||||
|
passwordStatus= PasswordStatus.fromJson(res['data']);
|
||||||
emit(SuccessState());
|
emit(SuccessState());
|
||||||
}else {
|
|
||||||
throw Exception('Failed to create password');
|
|
||||||
}
|
}
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
|
} on DioException catch (e){
|
||||||
} catch (e) {
|
final errorData = e.response!.data;
|
||||||
emit(FailedState(e.toString()));
|
String errorMessage = errorData['message'];
|
||||||
Navigator.pop(event.context!);
|
print('errorMessage==$errorData');
|
||||||
stateDialog(
|
emit(FailedState(errorMessage.toString()));
|
||||||
context: event.context!,
|
}
|
||||||
message: e.toString(),
|
|
||||||
title: 'Something Wrong'); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectDevice(
|
void selectDevice(
|
||||||
@ -476,13 +466,15 @@ class VisitorPasswordBloc
|
|||||||
String? message,
|
String? message,
|
||||||
String? title,
|
String? title,
|
||||||
dynamic actions,
|
dynamic actions,
|
||||||
|
Widget? widgeta,
|
||||||
}) {
|
}) {
|
||||||
return showCustomDialog(
|
return showCustomDialog(
|
||||||
context: context!,
|
context: context!,
|
||||||
message: message!,
|
message: message!,
|
||||||
iconPath: Assets.deviceNoteIcon,
|
iconPath: Assets.deviceNoteIcon,
|
||||||
title: title,
|
title: title,
|
||||||
dialogHeight: 150,
|
widget: widgeta,
|
||||||
|
dialogHeight: MediaQuery.of(context).size.height*0.3,
|
||||||
actions: actions ??
|
actions: actions ??
|
||||||
<Widget>[
|
<Widget>[
|
||||||
TextButton(
|
TextButton(
|
||||||
@ -494,4 +486,31 @@ class VisitorPasswordBloc
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Future<void> stateAndDeviseDialog({
|
||||||
|
// BuildContext? context,
|
||||||
|
// String? message,
|
||||||
|
// String? title,
|
||||||
|
// dynamic actions,
|
||||||
|
// }) {
|
||||||
|
// return showCustomDialog(
|
||||||
|
// context: context!,
|
||||||
|
// message: message!,
|
||||||
|
// iconPath: Assets.deviceNoteIcon,
|
||||||
|
// title: title,
|
||||||
|
// dialogHeight: 150,
|
||||||
|
// actions: actions ??
|
||||||
|
// <Widget>[
|
||||||
|
// TextButton(
|
||||||
|
// onPressed: () {
|
||||||
|
// Navigator.of(context).pop();
|
||||||
|
// },
|
||||||
|
// child: const Text('OK'),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
124
lib/pages/visitor_password/model/failed_operation.dart
Normal file
124
lib/pages/visitor_password/model/failed_operation.dart
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
class FailedOperation {
|
||||||
|
final bool success;
|
||||||
|
final dynamic deviceUuid;
|
||||||
|
final dynamic error;
|
||||||
|
|
||||||
|
FailedOperation({
|
||||||
|
required this.success,
|
||||||
|
required this.deviceUuid,
|
||||||
|
required this.error,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory FailedOperation.fromJson(Map<String, dynamic> json) {
|
||||||
|
return FailedOperation(
|
||||||
|
success: json['success'],
|
||||||
|
deviceUuid: json['deviceUuid'],
|
||||||
|
error: json['error'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'success': success,
|
||||||
|
'deviceUuid': deviceUuid,
|
||||||
|
'error': error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SuccessOperation {
|
||||||
|
final bool success;
|
||||||
|
// final Result result;
|
||||||
|
final String deviceUuid;
|
||||||
|
|
||||||
|
SuccessOperation({
|
||||||
|
required this.success,
|
||||||
|
// required this.result,
|
||||||
|
required this.deviceUuid,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory SuccessOperation.fromJson(Map<String, dynamic> json) {
|
||||||
|
return SuccessOperation(
|
||||||
|
success: json['success'],
|
||||||
|
// result: Result.fromJson(json['result']),
|
||||||
|
deviceUuid: json['deviceUuid'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'success': success,
|
||||||
|
// 'result': result.toJson(),
|
||||||
|
'deviceUuid': deviceUuid,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// class Result {
|
||||||
|
// final dynamic effectiveTime;
|
||||||
|
// final dynamic invalidTime;
|
||||||
|
// final dynamic offlineTempPassword;
|
||||||
|
// final dynamic offlineTempPasswordId;
|
||||||
|
// final dynamic offlineTempPasswordName;
|
||||||
|
//
|
||||||
|
// Result({
|
||||||
|
// required this.effectiveTime,
|
||||||
|
// required this.invalidTime,
|
||||||
|
// required this.offlineTempPassword,
|
||||||
|
// required this.offlineTempPasswordId,
|
||||||
|
// required this.offlineTempPasswordName,
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// factory Result.fromJson(Map<String, dynamic> json) {
|
||||||
|
// return Result(
|
||||||
|
// effectiveTime: json['effective_time'],
|
||||||
|
// invalidTime: json['invalid_time'],
|
||||||
|
// offlineTempPassword: json['offline_temp_password'].toString(),
|
||||||
|
// offlineTempPasswordId: json['offline_temp_password_id'],
|
||||||
|
// offlineTempPasswordName: json['offline_temp_password_name'],
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Map<String, dynamic> toJson() {
|
||||||
|
// return {
|
||||||
|
// 'effective_time': effectiveTime,
|
||||||
|
// 'invalid_time': invalidTime,
|
||||||
|
// 'offline_temp_password': offlineTempPassword,
|
||||||
|
// 'offline_temp_password_id': offlineTempPasswordId,
|
||||||
|
// 'offline_temp_password_name': offlineTempPasswordName,
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordStatus {
|
||||||
|
final List<SuccessOperation> successOperations;
|
||||||
|
final List<FailedOperation> failedOperations;
|
||||||
|
|
||||||
|
PasswordStatus({
|
||||||
|
required this.successOperations,
|
||||||
|
required this.failedOperations,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory PasswordStatus.fromJson(Map<String, dynamic> json) {
|
||||||
|
return PasswordStatus(
|
||||||
|
successOperations: (json['successOperations'] as List)
|
||||||
|
.map((i) => SuccessOperation.fromJson(i))
|
||||||
|
.toList(),
|
||||||
|
failedOperations: (json['failedOperations'] as List)
|
||||||
|
.map((i) => FailedOperation.fromJson(i))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'successOperations': successOperations.map((e) => e.toJson()).toList(),
|
||||||
|
'failedOperations': failedOperations.map((e) => e.toJson()).toList(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -32,6 +32,56 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
message: 'Password Created Successfully',
|
message: 'Password Created Successfully',
|
||||||
title: 'Send Success',
|
title: 'Send Success',
|
||||||
|
widgeta:Column(
|
||||||
|
children: [
|
||||||
|
if(visitorBloc.passwordStatus!.failedOperations.isNotEmpty)
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
const Text('Failed Devises'),
|
||||||
|
SizedBox(
|
||||||
|
width: 200,
|
||||||
|
height: 50,
|
||||||
|
child: ListView.builder(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount:visitorBloc.passwordStatus!.failedOperations.length ,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.all(5),
|
||||||
|
|
||||||
|
decoration: containerDecoration,
|
||||||
|
height: 45,
|
||||||
|
child: Center(child: Text(visitorBloc.passwordStatus!.failedOperations[index].deviceUuid)),
|
||||||
|
);
|
||||||
|
},),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if(visitorBloc.passwordStatus!.successOperations.isNotEmpty)
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
const Text('Success Devises'),
|
||||||
|
SizedBox(
|
||||||
|
width: 200,
|
||||||
|
height: 50,
|
||||||
|
child: ListView.builder(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount:visitorBloc.passwordStatus!.successOperations.length ,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.all(5),
|
||||||
|
decoration: containerDecoration,
|
||||||
|
height: 45,
|
||||||
|
child: Center(child: Text(visitorBloc.passwordStatus!.successOperations[index].deviceUuid)),
|
||||||
|
);
|
||||||
|
},),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
);
|
);
|
||||||
} else if (state is FailedState) {
|
} else if (state is FailedState) {
|
||||||
visitorBloc.stateDialog(
|
visitorBloc.stateDialog(
|
||||||
@ -111,7 +161,12 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Flexible(
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: size.width*0.12,
|
||||||
child: RadioListTile<String>(
|
child: RadioListTile<String>(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
title: Text('Online Password',
|
title: Text('Online Password',
|
||||||
@ -129,10 +184,10 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Flexible(
|
SizedBox(
|
||||||
|
width: size.width*0.12,
|
||||||
child: RadioListTile<String>(
|
child: RadioListTile<String>(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
|
|
||||||
title: Text('Offline Password',
|
title: Text('Offline Password',
|
||||||
style:text ),
|
style:text ),
|
||||||
value: 'Offline Password',
|
value: 'Offline Password',
|
||||||
@ -146,10 +201,10 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Flexible(
|
SizedBox(
|
||||||
|
width: size.width*0.12,
|
||||||
child: RadioListTile<String>(
|
child: RadioListTile<String>(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
|
|
||||||
title: Text('Dynamic Password',
|
title: Text('Dynamic Password',
|
||||||
style: text,),
|
style: text,),
|
||||||
value: 'Dynamic Password',
|
value: 'Dynamic Password',
|
||||||
@ -166,12 +221,31 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
)),
|
||||||
|
const Spacer(flex: 2,),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
|
if(visitorBloc.accessTypeSelected == 'Online Password')
|
||||||
Text(
|
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',
|
'Only currently online devices can be selected. It is recommended to use when the device network is stable, and the system randomly generates a digital password',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: ColorsManager.grayColor,fontSize: 9),
|
||||||
|
),
|
||||||
|
if(visitorBloc.accessTypeSelected == 'Offline Password')
|
||||||
|
Text(
|
||||||
|
'Unaffected by the online status of the device, you can select online or offline device, and the system randomly generates a digital password',
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: ColorsManager.grayColor,fontSize: 9),),
|
color: ColorsManager.grayColor,fontSize: 9),),
|
||||||
|
|
||||||
|
if(visitorBloc.accessTypeSelected == 'Dynamic Password')
|
||||||
|
Text(
|
||||||
|
'Quick and short-acting password, only valid within 5 minutes after creation, the system randomly generates a digital password.',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
color: ColorsManager.grayColor,fontSize: 9),),
|
||||||
|
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
)
|
)
|
||||||
@ -193,7 +267,8 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Flexible(
|
SizedBox(
|
||||||
|
width: size.width*0.12,
|
||||||
child: RadioListTile<String>(
|
child: RadioListTile<String>(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
title: Text('One-Time',
|
title: Text('One-Time',
|
||||||
@ -205,13 +280,13 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
: visitorBloc.usageFrequencySelected,
|
: visitorBloc.usageFrequencySelected,
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
context.read<VisitorPasswordBloc>()
|
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
|
||||||
.add(SelectUsageFrequency(value));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Flexible(
|
SizedBox(
|
||||||
|
width: size.width*0.12,
|
||||||
child: RadioListTile<String>(
|
child: RadioListTile<String>(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
title: Text('Periodic',
|
title: Text('Periodic',
|
||||||
@ -230,10 +305,35 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
//One-Time
|
||||||
|
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
||||||
|
visitorBloc.accessTypeSelected == 'Online Password')
|
||||||
Text('Within the validity period, each device can be unlocked only once.',
|
Text('Within the validity period, each device can be unlocked only once.',
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
color: ColorsManager.grayColor,fontSize: 9),
|
color: ColorsManager.grayColor,fontSize: 9),
|
||||||
)
|
),
|
||||||
|
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
|
||||||
|
visitorBloc.accessTypeSelected == 'Offline Password')
|
||||||
|
Text('Within the validity period, there is no limit to the number of times each device can be unlocked.',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
color: ColorsManager.grayColor,fontSize: 9),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Periodic
|
||||||
|
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||||
|
visitorBloc.accessTypeSelected == 'Offline Password')
|
||||||
|
Text('Within the validity period, there is no limit to the number of times each device can be unlocked, and it should be used at least once within 24 hours after the entry into force.',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
color: ColorsManager.grayColor,fontSize: 9),
|
||||||
|
),
|
||||||
|
|
||||||
|
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||||
|
visitorBloc.accessTypeSelected == 'Online Password')
|
||||||
|
Text('Within the validity period, there is no limit to the number of times each device can be unlocked.',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
|
color: ColorsManager.grayColor,fontSize: 9),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
@ -247,19 +347,37 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
title: 'Access Period',
|
title: 'Access Period',
|
||||||
size: size,
|
size: size,
|
||||||
endTime: () {
|
endTime: () {
|
||||||
|
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||||
|
visitorBloc.accessTypeSelected == 'Offline Password'){
|
||||||
|
visitorBloc.add(SelectTimeEvent(
|
||||||
|
context: context,
|
||||||
|
isEffective: false));
|
||||||
|
}else{
|
||||||
visitorBloc.add(SelectTimeVisitorPassword(
|
visitorBloc.add(SelectTimeVisitorPassword(
|
||||||
context: context,
|
context: context,
|
||||||
isStart: false,
|
isStart: false,
|
||||||
isRepeat: false));
|
isRepeat: false));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
startTime: () {
|
startTime: () {
|
||||||
|
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||||
|
visitorBloc.accessTypeSelected == 'Offline Password'){
|
||||||
|
visitorBloc.add(SelectTimeEvent(context: context, isEffective: true));
|
||||||
|
}else{
|
||||||
visitorBloc.add(SelectTimeVisitorPassword(
|
visitorBloc.add(SelectTimeVisitorPassword(
|
||||||
context: context,
|
context: context,
|
||||||
isStart: true,
|
isStart: true,
|
||||||
isRepeat: false));
|
isRepeat: false));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
firstString: visitorBloc.startTimeAccess.toString(),
|
|
||||||
secondString: visitorBloc.endTimeAccess.toString(),
|
firstString:
|
||||||
|
(visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||||
|
visitorBloc.accessTypeSelected == 'Offline Password')?
|
||||||
|
visitorBloc.effectiveTime:visitorBloc.startTimeAccess.toString(),
|
||||||
|
secondString: (visitorBloc.usageFrequencySelected == 'Periodic' &&
|
||||||
|
visitorBloc.accessTypeSelected == 'Offline Password')?
|
||||||
|
visitorBloc.expirationTime:visitorBloc.endTimeAccess.toString(),
|
||||||
icon: Assets.calendarIcon
|
icon: Assets.calendarIcon
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
@ -367,19 +485,84 @@ class VisitorPasswordDialog extends StatelessWidget {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (visitorBloc.forgetFormKey.currentState!.validate()) {
|
if (visitorBloc.forgetFormKey.currentState!.validate()) {
|
||||||
if(visitorBloc.selectedDevices.isNotEmpty){
|
if(visitorBloc.selectedDevices.isNotEmpty){
|
||||||
|
if(visitorBloc.usageFrequencySelected == 'One-Time' && visitorBloc.accessTypeSelected == 'Offline Password'){
|
||||||
|
setPasswordFunction(context, size, visitorBloc);
|
||||||
|
}else{
|
||||||
if(visitorBloc.effectiveTimeTimeStamp!=null&&visitorBloc.expirationTimeTimeStamp!=null) {
|
if(visitorBloc.effectiveTimeTimeStamp!=null&&visitorBloc.expirationTimeTimeStamp!=null) {
|
||||||
|
if(isRepeat==true){
|
||||||
|
if(visitorBloc.expirationTime!='End Time'&&visitorBloc.effectiveTime!='Start Time'&&visitorBloc.selectedDays.isNotEmpty){
|
||||||
setPasswordFunction(context, size, visitorBloc);
|
setPasswordFunction(context, size, visitorBloc);
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
visitorBloc.stateDialog(context:
|
||||||
|
context,message: 'Please select days and fill start time and end time to continue',title: 'Access Period');
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
setPasswordFunction(context, size, visitorBloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
else{
|
else{
|
||||||
visitorBloc.stateDialog(context:
|
visitorBloc.stateDialog(context:
|
||||||
context,message: 'Please select Access Period to continue',title: 'Access Period');
|
context,message: 'Please select Access Period to continue',title: 'Access Period');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
visitorBloc.stateDialog(context:
|
visitorBloc.stateDialog(context:
|
||||||
context,message: 'Please select devices to continue',title: 'Select Devices');
|
context,message: 'Please select devices to continue',title: 'Select Devices');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// onPressed: () {
|
||||||
|
// if (visitorBloc.forgetFormKey.currentState!.validate()) {
|
||||||
|
// if (visitorBloc.selectedDevices.isNotEmpty) {
|
||||||
|
// switch (visitorBloc.usageFrequencySelected) {
|
||||||
|
// case 'One-Time':
|
||||||
|
// if (visitorBloc.accessTypeSelected == 'Offline Password') {
|
||||||
|
// setPasswordFunction(context, size, visitorBloc);
|
||||||
|
// } else {
|
||||||
|
// visitorBloc.stateDialog(
|
||||||
|
// context: context,
|
||||||
|
// message: 'Invalid combination of Access Type and Usage Frequency.',
|
||||||
|
// title: 'Error',
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// if (visitorBloc.effectiveTimeTimeStamp != null && visitorBloc.expirationTimeTimeStamp != null) {
|
||||||
|
// if (isRepeat) {
|
||||||
|
// if (visitorBloc.expirationTime != 'End Time' &&
|
||||||
|
// visitorBloc.effectiveTime != 'Start Time' &&
|
||||||
|
// visitorBloc.selectedDays.isNotEmpty) {
|
||||||
|
// setPasswordFunction(context, size, visitorBloc);
|
||||||
|
// } else {
|
||||||
|
// visitorBloc.stateDialog(
|
||||||
|
// context: context,
|
||||||
|
// message: 'Please select days and fill start time and end time to continue',
|
||||||
|
// title: 'Access Period',
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// setPasswordFunction(context, size, visitorBloc);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// visitorBloc.stateDialog(
|
||||||
|
// context: context,
|
||||||
|
// message: 'Please select Access Period to continue',
|
||||||
|
// title: 'Access Period',
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// visitorBloc.stateDialog(
|
||||||
|
// context: context,
|
||||||
|
// message: 'Please select devices to continue',
|
||||||
|
// title: 'Select Devices',
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
child: Text('Ok', style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
child: Text('Ok', style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
|
@ -3,6 +3,7 @@ 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/device_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/visitor_password/model/failed_operation.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/model/schedule_model.dart';
|
import 'package:syncrow_web/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';
|
||||||
@ -49,14 +50,13 @@ class AccessMangApi{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> postOnlineOneTime({
|
Future postOnlineOneTime({
|
||||||
String? email,
|
String? email,
|
||||||
String? passwordName,
|
String? passwordName,
|
||||||
String? password,
|
String? password,
|
||||||
String? effectiveTime,
|
String? effectiveTime,
|
||||||
String? invalidTime,
|
String? invalidTime,
|
||||||
List<String>? devicesUuid}) async {
|
List<String>? devicesUuid}) async {
|
||||||
try {
|
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOnlineOneTime,
|
path: ApiEndpoints.sendOnlineOneTime,
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
@ -69,19 +69,11 @@ class AccessMangApi{
|
|||||||
}),
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
if(json['statusCode'].toString()=='201'){
|
return json;
|
||||||
return true;
|
|
||||||
}else{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} on DioException catch (e) {
|
|
||||||
debugPrint('Error: ${e.message}');
|
|
||||||
debugPrint('Error fetching ${e.response!.statusMessage}');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future postOnlineMultipleTime({
|
Future postOnlineMultipleTime({
|
||||||
@ -92,7 +84,6 @@ class AccessMangApi{
|
|||||||
String? passwordName,
|
String? passwordName,
|
||||||
List<Schedule>? scheduleList,
|
List<Schedule>? scheduleList,
|
||||||
List<String>? devicesUuid}) async {
|
List<String>? devicesUuid}) async {
|
||||||
try {
|
|
||||||
Map<String, dynamic> body = {
|
Map<String, dynamic> body = {
|
||||||
"email": email,
|
"email": email,
|
||||||
"devicesUuid": devicesUuid,
|
"devicesUuid": devicesUuid,
|
||||||
@ -109,25 +100,16 @@ class AccessMangApi{
|
|||||||
body: jsonEncode(body),
|
body: jsonEncode(body),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
if(json['data']['successOperations'][0]['success'].toString()=='true'){
|
return json;
|
||||||
return true;
|
|
||||||
}else{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} on DioException catch (e){
|
|
||||||
debugPrint('Error fetching ${e.type.name}');
|
|
||||||
debugPrint('Error fetching ${e.response!.statusMessage}');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OffLine One Time Password
|
// OffLine One Time Password
|
||||||
|
|
||||||
Future postOffLineOneTime({String? email,String? passwordName,List<String>? devicesUuid}) async {
|
Future postOffLineOneTime({String? email,String? passwordName,List<String>? devicesUuid}) async {
|
||||||
try {
|
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOffLineOneTime,
|
path: ApiEndpoints.sendOffLineOneTime,
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
@ -137,19 +119,11 @@ class AccessMangApi{
|
|||||||
}),
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
if (json['data']['successOperations'][0]['success'].toString() ==
|
return json;
|
||||||
'true') {
|
},
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
|
||||||
debugPrint('Error fetching $e');
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future postOffLineMultipleTime({
|
Future postOffLineMultipleTime({
|
||||||
@ -158,32 +132,31 @@ class AccessMangApi{
|
|||||||
String? effectiveTime,
|
String? effectiveTime,
|
||||||
String? invalidTime,
|
String? invalidTime,
|
||||||
List<String>? devicesUuid
|
List<String>? devicesUuid
|
||||||
|
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
print(jsonEncode({
|
||||||
final response = await HTTPService().post(
|
|
||||||
path: ApiEndpoints.sendOffLineOneTime,
|
|
||||||
body: jsonEncode({
|
|
||||||
"email": email,
|
"email": email,
|
||||||
"devicesUuid":devicesUuid,
|
"devicesUuid": devicesUuid,
|
||||||
"passwordName": passwordName,
|
"passwordName": passwordName,
|
||||||
"effectiveTime": effectiveTime,
|
"effectiveTime": effectiveTime,
|
||||||
"invalidTime": invalidTime
|
"invalidTime": invalidTime,
|
||||||
|
}));
|
||||||
|
final response = await HTTPService().post(
|
||||||
|
path: ApiEndpoints.sendOffLineMultipleTime,
|
||||||
|
body: jsonEncode({
|
||||||
|
"email": email,
|
||||||
|
"devicesUuid": devicesUuid,
|
||||||
|
"passwordName": passwordName,
|
||||||
|
"effectiveTime": effectiveTime,
|
||||||
|
"invalidTime": invalidTime,
|
||||||
}),
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
if (json['data']['successOperations'][0]['success'].toString() ==
|
return json;
|
||||||
'true') {
|
},
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
|
||||||
debugPrint('Error fetching $e');
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,7 +62,8 @@ class AuthenticationAPI {
|
|||||||
debugPrint('Error: ${e.response!.statusCode} - ${e.response!.statusMessage}');
|
debugPrint('Error: ${e.response!.statusCode} - ${e.response!.statusMessage}');
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
debugPrint('Error: ${e.message}');
|
debugPrint('Error: ${e.message}');
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -32,4 +32,9 @@ abstract class ColorsManager {
|
|||||||
static const Color blueColor = Color(0xFF0036E6);
|
static const Color blueColor = Color(0xFF0036E6);
|
||||||
static const Color boxColor = Color(0xFFF5F6F7);
|
static const Color boxColor = Color(0xFFF5F6F7);
|
||||||
static const Color boxDivider = Color(0xFFE0E0E0);
|
static const Color boxDivider = Color(0xFFE0E0E0);
|
||||||
|
static const Color blue1 = Color(0xFF0036E6);
|
||||||
|
static const Color blue2 = Color(0xFF0026A2);
|
||||||
|
static const Color blue3 = Color(0xFF00165E);
|
||||||
|
static const Color blue4 = Color(0xFF001E7E);
|
||||||
}
|
}
|
||||||
|
//0036E6
|
24
pubspec.lock
24
pubspec.lock
@ -260,18 +260,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker
|
name: leak_tracker
|
||||||
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
|
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.0.5"
|
version: "10.0.4"
|
||||||
leak_tracker_flutter_testing:
|
leak_tracker_flutter_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_flutter_testing
|
name: leak_tracker_flutter_testing
|
||||||
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
|
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.5"
|
version: "3.0.3"
|
||||||
leak_tracker_testing:
|
leak_tracker_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -300,18 +300,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.11.1"
|
version: "0.8.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
|
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0"
|
version: "1.12.0"
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -521,10 +521,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
|
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.2"
|
version: "0.7.0"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -569,10 +569,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
|
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "14.2.5"
|
version: "14.2.1"
|
||||||
web:
|
web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
Reference in New Issue
Block a user