Merge branch 'dev' of https://github.com/SyncrowIOT/web into dev

This commit is contained in:
Faris Armoush
2025-06-28 13:16:16 +03:00
10 changed files with 168 additions and 76 deletions

View File

@ -14,12 +14,21 @@ class OccupancyHeatMapModel extends Equatable {
}); });
factory OccupancyHeatMapModel.fromJson(Map<String, dynamic> json) { factory OccupancyHeatMapModel.fromJson(Map<String, dynamic> json) {
final eventDate = json['event_date'] as String?;
final year = eventDate?.split('-')[0];
final month = eventDate?.split('-')[1];
final day = eventDate?.split('-')[2];
return OccupancyHeatMapModel( return OccupancyHeatMapModel(
uuid: json['uuid'] as String? ?? '', uuid: json['uuid'] as String? ?? '',
eventDate: DateTime.parse( eventDate: DateTime.utc(
json['event_date'] as String? ?? '${DateTime.now()}', int.parse(year ?? '2025'),
int.parse(month ?? '1'),
int.parse(day ?? '1'),
), ),
countTotalPresenceDetected: json['count_total_presence_detected'] as int? ?? 0, countTotalPresenceDetected: num.parse(
json['count_total_presence_detected']?.toString() ?? '0',
).toInt(),
); );
} }

View File

@ -6,7 +6,7 @@ enum AqiType {
aqi('AQI', '', 'aqi'), aqi('AQI', '', 'aqi'),
pm25('PM2.5', 'µg/m³', 'pm25'), pm25('PM2.5', 'µg/m³', 'pm25'),
pm10('PM10', 'µg/m³', 'pm10'), pm10('PM10', 'µg/m³', 'pm10'),
hcho('HCHO', 'mg/m³', 'cho2'), hcho('HCHO', 'mg/m³', 'ch2o'),
tvoc('TVOC', 'mg/m³', 'voc'), tvoc('TVOC', 'mg/m³', 'voc'),
co2('CO2', 'ppm', 'co2'); co2('CO2', 'ppm', 'co2');

View File

@ -27,16 +27,30 @@ class AnalyticsDeviceDropdown extends StatelessWidget {
width: 1, width: 1,
), ),
), ),
child: Visibility(
visible: state.status != AnalyticsDevicesStatus.loading,
replacement: _buildLoadingIndicator(),
child: Visibility( child: Visibility(
visible: state.devices.isNotEmpty, visible: state.devices.isNotEmpty,
replacement: _buildNoDevicesFound(context), replacement: _buildNoDevicesFound(context),
child: _buildDevicesDropdown(context, state), child: _buildDevicesDropdown(context, state),
), ),
),
); );
}, },
); );
} }
Widget _buildLoadingIndicator() {
return const Center(
child: SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(strokeWidth: 3),
),
);
}
static const _defaultPadding = EdgeInsetsDirectional.symmetric( static const _defaultPadding = EdgeInsetsDirectional.symmetric(
horizontal: 20, horizontal: 20,
vertical: 2, vertical: 2,

View File

@ -14,14 +14,17 @@ class TotalEnergyConsumptionChart extends StatelessWidget {
return Expanded( return Expanded(
child: LineChart( child: LineChart(
LineChartData( LineChartData(
maxY: chartData.isEmpty
? null
: chartData.map((e) => e.value).reduce((a, b) => a > b ? a : b) + 250,
clipData: const FlClipData.vertical(), clipData: const FlClipData.vertical(),
titlesData: EnergyManagementChartsHelper.titlesData( titlesData: EnergyManagementChartsHelper.titlesData(
context, context,
leftTitlesInterval: 250, leftTitlesInterval: 500,
), ),
gridData: EnergyManagementChartsHelper.gridData().copyWith( gridData: EnergyManagementChartsHelper.gridData().copyWith(
checkToShowHorizontalLine: (value) => true, checkToShowHorizontalLine: (value) => true,
horizontalInterval: 250, horizontalInterval: 500,
), ),
borderData: EnergyManagementChartsHelper.borderData(), borderData: EnergyManagementChartsHelper.borderData(),
lineTouchData: EnergyManagementChartsHelper.lineTouchData(), lineTouchData: EnergyManagementChartsHelper.lineTouchData(),
@ -29,7 +32,6 @@ class TotalEnergyConsumptionChart extends StatelessWidget {
), ),
duration: Duration.zero, duration: Duration.zero,
curve: Curves.easeIn, curve: Curves.easeIn,
), ),
); );
} }

View File

@ -52,7 +52,7 @@ class _InteractiveHeatMapState extends State<InteractiveHeatMap> {
color: Colors.transparent, color: Colors.transparent,
child: Transform.translate( child: Transform.translate(
offset: Offset(-(widget.cellSize * 2.5), -50), offset: Offset(-(widget.cellSize * 2.5), -50),
child: HeatMapTooltip(date: item.date, value: item.value), child: HeatMapTooltip(date: item.date.toUtc(), value: item.value),
), ),
), ),
), ),

View File

@ -36,7 +36,8 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
////////////////////////////// forget password ////////////////////////////////// ////////////////////////////// forget password //////////////////////////////////
final TextEditingController forgetEmailController = TextEditingController(); final TextEditingController forgetEmailController = TextEditingController();
final TextEditingController forgetPasswordController = TextEditingController(); final TextEditingController forgetPasswordController =
TextEditingController();
final TextEditingController forgetOtp = TextEditingController(); final TextEditingController forgetOtp = TextEditingController();
final forgetFormKey = GlobalKey<FormState>(); final forgetFormKey = GlobalKey<FormState>();
final forgetEmailKey = GlobalKey<FormState>(); final forgetEmailKey = GlobalKey<FormState>();
@ -53,7 +54,8 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
return; return;
} }
_remainingTime = 1; _remainingTime = 1;
add(UpdateTimerEvent(remainingTime: _remainingTime, isButtonEnabled: false)); add(UpdateTimerEvent(
remainingTime: _remainingTime, isButtonEnabled: false));
try { try {
forgetEmailValidate = ''; forgetEmailValidate = '';
_remainingTime = (await AuthenticationAPI.sendOtp( _remainingTime = (await AuthenticationAPI.sendOtp(
@ -90,7 +92,8 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
_timer?.cancel(); _timer?.cancel();
add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true)); add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true));
} else { } else {
add(UpdateTimerEvent(remainingTime: _remainingTime, isButtonEnabled: false)); add(UpdateTimerEvent(
remainingTime: _remainingTime, isButtonEnabled: false));
} }
}); });
} }
@ -100,7 +103,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
emit(const TimerState(isButtonEnabled: true, remainingTime: 0)); emit(const TimerState(isButtonEnabled: true, remainingTime: 0));
} }
Future<void> changePassword( Future<void> changePassword(
ChangePasswordEvent event, Emitter<AuthState> emit) async { ChangePasswordEvent event, Emitter<AuthState> emit) async {
emit(LoadingForgetState()); emit(LoadingForgetState());
try { try {
@ -122,7 +125,6 @@ Future<void> changePassword(
} }
} }
String? validateCode(String? value) { String? validateCode(String? value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
return 'Code is required'; return 'Code is required';
@ -131,7 +133,9 @@ Future<void> changePassword(
} }
void _onUpdateTimer(UpdateTimerEvent event, Emitter<AuthState> emit) { void _onUpdateTimer(UpdateTimerEvent event, Emitter<AuthState> emit) {
emit(TimerState(isButtonEnabled: event.isButtonEnabled, remainingTime: event.remainingTime)); emit(TimerState(
isButtonEnabled: event.isButtonEnabled,
remainingTime: event.remainingTime));
} }
///////////////////////////////////// login ///////////////////////////////////// ///////////////////////////////////// login /////////////////////////////////////
@ -151,7 +155,6 @@ Future<void> changePassword(
static UserModel? user; static UserModel? user;
bool showValidationMessage = false; bool showValidationMessage = false;
void _login(LoginButtonPressed event, Emitter<AuthState> emit) async { void _login(LoginButtonPressed event, Emitter<AuthState> emit) async {
emit(AuthLoading()); emit(AuthLoading());
if (isChecked) { if (isChecked) {
@ -170,11 +173,11 @@ Future<void> changePassword(
); );
} on APIException catch (e) { } on APIException catch (e) {
validate = e.message; validate = e.message;
emit(LoginInitial()); emit(LoginFailure(error: validate));
return; return;
} catch (e) { } catch (e) {
validate = 'Something went wrong'; validate = 'Something went wrong';
emit(LoginInitial()); emit(LoginFailure(error: validate));
return; return;
} }
@ -197,7 +200,6 @@ Future<void> changePassword(
} }
} }
checkBoxToggle( checkBoxToggle(
CheckBoxEvent event, CheckBoxEvent event,
Emitter<AuthState> emit, Emitter<AuthState> emit,
@ -339,12 +341,14 @@ Future<void> changePassword(
static Future<String> getTokenAndValidate() async { static Future<String> getTokenAndValidate() async {
try { try {
const storage = FlutterSecureStorage(); const storage = FlutterSecureStorage();
final firstLaunch = final firstLaunch = await SharedPreferencesHelper.readBoolFromSP(
await SharedPreferencesHelper.readBoolFromSP(StringsManager.firstLaunch) ?? true; StringsManager.firstLaunch) ??
true;
if (firstLaunch) { if (firstLaunch) {
storage.deleteAll(); storage.deleteAll();
} }
await SharedPreferencesHelper.saveBoolToSP(StringsManager.firstLaunch, false); await SharedPreferencesHelper.saveBoolToSP(
StringsManager.firstLaunch, false);
final value = await storage.read(key: Token.loginAccessTokenKey) ?? ''; final value = await storage.read(key: Token.loginAccessTokenKey) ?? '';
if (value.isEmpty) { if (value.isEmpty) {
return 'Token not found'; return 'Token not found';
@ -397,7 +401,9 @@ Future<void> changePassword(
final String formattedTime = [ final String formattedTime = [
if (days > 0) '${days}d', // Append 'd' for days if (days > 0) '${days}d', // Append 'd' for days
if (days > 0 || hours > 0) if (days > 0 || hours > 0)
hours.toString().padLeft(2, '0'), // Show hours if there are days or hours hours
.toString()
.padLeft(2, '0'), // Show hours if there are days or hours
minutes.toString().padLeft(2, '0'), minutes.toString().padLeft(2, '0'),
seconds.toString().padLeft(2, '0'), seconds.toString().padLeft(2, '0'),
].join(':'); ].join(':');

View File

@ -62,7 +62,8 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
final buttonLabel = final buttonLabel =
(selectedDevices.length > 1) ? 'Batch Control' : 'Control'; (selectedDevices.length > 1) ? 'Batch Control' : 'Control';
final isAnyDeviceOffline =
selectedDevices.any((element) => !(element.online ?? false));
return Row( return Row(
children: [ children: [
Expanded(child: SpaceTreeView( Expanded(child: SpaceTreeView(
@ -103,8 +104,26 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
decoration: containerDecoration, decoration: containerDecoration,
child: Center( child: Center(
child: DefaultButton( child: DefaultButton(
backgroundColor: isAnyDeviceOffline
? ColorsManager.primaryColor
.withValues(alpha: 0.1)
: null,
onPressed: isControlButtonEnabled onPressed: isControlButtonEnabled
? () { ? () {
if (isAnyDeviceOffline) {
ScaffoldMessenger.of(context)
.showSnackBar(
const SnackBar(
content: Text(
'This Device is Offline',
),
duration:
Duration(seconds: 2),
),
);
return;
}
if (selectedDevices.length == 1) { if (selectedDevices.length == 1) {
showDialog( showDialog(
context: context, context: context,

View File

@ -1,7 +1,9 @@
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';
import 'package:syncrow_web/pages/auth/model/user_model.dart';
import 'package:syncrow_web/pages/common/bloc/project_manager.dart'; import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
import 'package:syncrow_web/pages/roles_and_permission/model/roles_user_model.dart';
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_bloc.dart';
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_event.dart';
import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart'; import 'package:syncrow_web/pages/roles_and_permission/users_page/add_user_dialog/bloc/users_status.dart';
@ -12,8 +14,11 @@ import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
class EditUserDialog extends StatefulWidget { class EditUserDialog extends StatefulWidget {
final String? userId; final RolesUserModel? user;
const EditUserDialog({super.key, this.userId}); const EditUserDialog({
super.key,
this.user,
});
@override @override
_EditUserDialogState createState() => _EditUserDialogState(); _EditUserDialogState createState() => _EditUserDialogState();
@ -28,10 +33,11 @@ class _EditUserDialogState extends State<EditUserDialog> {
create: (BuildContext context) => UsersBloc() create: (BuildContext context) => UsersBloc()
// ..add(const LoadCommunityAndSpacesEvent()) // ..add(const LoadCommunityAndSpacesEvent())
..add(const RoleEvent()) ..add(const RoleEvent())
..add(GetUserByIdEvent(uuid: widget.userId)), ..add(GetUserByIdEvent(uuid: widget.user!.uuid)),
child: BlocConsumer<UsersBloc, UsersState>(listener: (context, state) { child: BlocConsumer<UsersBloc, UsersState>(listener: (context, state) {
if (state is SpacesLoadedState) { if (state is SpacesLoadedState) {
BlocProvider.of<UsersBloc>(context).add(GetUserByIdEvent(uuid: widget.userId)); BlocProvider.of<UsersBloc>(context)
.add(GetUserByIdEvent(uuid: widget.user!.uuid));
} }
}, builder: (context, state) { }, builder: (context, state) {
final _blocRole = BlocProvider.of<UsersBloc>(context); final _blocRole = BlocProvider.of<UsersBloc>(context);
@ -39,7 +45,8 @@ class _EditUserDialogState extends State<EditUserDialog> {
return Dialog( return Dialog(
child: Container( child: Container(
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(20))), color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(20))),
width: 900, width: 900,
child: Column( child: Column(
children: [ children: [
@ -68,7 +75,8 @@ class _EditUserDialogState extends State<EditUserDialog> {
children: [ children: [
_buildStep1Indicator(1, "Basics", _blocRole), _buildStep1Indicator(1, "Basics", _blocRole),
_buildStep2Indicator(2, "Spaces", _blocRole), _buildStep2Indicator(2, "Spaces", _blocRole),
_buildStep3Indicator(3, "Role & Permissions", _blocRole), _buildStep3Indicator(
3, "Role & Permissions", _blocRole),
], ],
), ),
), ),
@ -86,7 +94,7 @@ class _EditUserDialogState extends State<EditUserDialog> {
children: [ children: [
const SizedBox(height: 10), const SizedBox(height: 10),
Expanded( Expanded(
child: _getFormContent(widget.userId), child: _getFormContent(widget.user!),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
], ],
@ -116,13 +124,14 @@ class _EditUserDialogState extends State<EditUserDialog> {
if (currentStep < 3) { if (currentStep < 3) {
currentStep++; currentStep++;
if (currentStep == 2) { if (currentStep == 2) {
_blocRole.add(CheckStepStatus(isEditUser: true)); _blocRole
.add(CheckStepStatus(isEditUser: true));
} else if (currentStep == 3) { } else if (currentStep == 3) {
_blocRole.add(const CheckSpacesStepStatus()); _blocRole.add(const CheckSpacesStepStatus());
} }
} else { } else {
_blocRole _blocRole.add(EditInviteUsers(
.add(EditInviteUsers(context: context, userId: widget.userId!)); context: context, userId: widget.user!.uuid));
} }
}); });
}, },
@ -131,7 +140,8 @@ class _EditUserDialogState extends State<EditUserDialog> {
style: TextStyle( style: TextStyle(
color: (_blocRole.isCompleteSpaces == false || color: (_blocRole.isCompleteSpaces == false ||
_blocRole.isCompleteBasics == false || _blocRole.isCompleteBasics == false ||
_blocRole.isCompleteRolePermissions == false) && _blocRole.isCompleteRolePermissions ==
false) &&
currentStep == 3 currentStep == 3
? ColorsManager.grayColor ? ColorsManager.grayColor
: ColorsManager.secondaryColor), : ColorsManager.secondaryColor),
@ -146,15 +156,15 @@ class _EditUserDialogState extends State<EditUserDialog> {
})); }));
} }
Widget _getFormContent(userid) { Widget _getFormContent(RolesUserModel user) {
switch (currentStep) { switch (currentStep) {
case 1: case 1:
return BasicsView( return BasicsView(
userId: userid, userId: user.uuid,
); );
case 2: case 2:
return SpacesAccessView( return SpacesAccessView(
userId: userid, userId: user.uuid,
); );
case 3: case 3:
return const RolesAndPermission(); return const RolesAndPermission();
@ -166,6 +176,7 @@ class _EditUserDialogState extends State<EditUserDialog> {
int step3 = 0; int step3 = 0;
Widget _buildStep1Indicator(int step, String label, UsersBloc bloc) { Widget _buildStep1Indicator(int step, String label, UsersBloc bloc) {
final isCurrentStep = currentStep == step;
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
setState(() { setState(() {
@ -189,7 +200,7 @@ class _EditUserDialogState extends State<EditUserDialog> {
child: Row( child: Row(
children: [ children: [
SvgPicture.asset( SvgPicture.asset(
currentStep == step isCurrentStep
? Assets.currentProcessIcon ? Assets.currentProcessIcon
: bloc.isCompleteBasics == false : bloc.isCompleteBasics == false
? Assets.wrongProcessIcon ? Assets.wrongProcessIcon
@ -204,8 +215,11 @@ class _EditUserDialogState extends State<EditUserDialog> {
label, label,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: currentStep == step ? ColorsManager.blackColor : ColorsManager.greyColor, color: isCurrentStep
fontWeight: currentStep == step ? FontWeight.bold : FontWeight.normal, ? ColorsManager.blackColor
: ColorsManager.greyColor,
fontWeight:
isCurrentStep ? FontWeight.bold : FontWeight.normal,
), ),
), ),
], ],
@ -229,6 +243,7 @@ class _EditUserDialogState extends State<EditUserDialog> {
} }
Widget _buildStep2Indicator(int step, String label, UsersBloc bloc) { Widget _buildStep2Indicator(int step, String label, UsersBloc bloc) {
final isCurrentStep = currentStep == step;
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
setState(() { setState(() {
@ -248,7 +263,7 @@ class _EditUserDialogState extends State<EditUserDialog> {
child: Row( child: Row(
children: [ children: [
SvgPicture.asset( SvgPicture.asset(
currentStep == step isCurrentStep
? Assets.currentProcessIcon ? Assets.currentProcessIcon
: bloc.isCompleteSpaces == false : bloc.isCompleteSpaces == false
? Assets.wrongProcessIcon ? Assets.wrongProcessIcon
@ -263,8 +278,11 @@ class _EditUserDialogState extends State<EditUserDialog> {
label, label,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: currentStep == step ? ColorsManager.blackColor : ColorsManager.greyColor, color: isCurrentStep
fontWeight: currentStep == step ? FontWeight.bold : FontWeight.normal, ? ColorsManager.blackColor
: ColorsManager.greyColor,
fontWeight:
isCurrentStep ? FontWeight.bold : FontWeight.normal,
), ),
), ),
], ],
@ -288,6 +306,7 @@ class _EditUserDialogState extends State<EditUserDialog> {
} }
Widget _buildStep3Indicator(int step, String label, UsersBloc bloc) { Widget _buildStep3Indicator(int step, String label, UsersBloc bloc) {
final isCurrentStep = currentStep == step;
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
setState(() { setState(() {
@ -306,7 +325,7 @@ class _EditUserDialogState extends State<EditUserDialog> {
child: Row( child: Row(
children: [ children: [
SvgPicture.asset( SvgPicture.asset(
currentStep == step isCurrentStep
? Assets.currentProcessIcon ? Assets.currentProcessIcon
: bloc.isCompleteRolePermissions == false : bloc.isCompleteRolePermissions == false
? Assets.wrongProcessIcon ? Assets.wrongProcessIcon
@ -321,8 +340,11 @@ class _EditUserDialogState extends State<EditUserDialog> {
label, label,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: currentStep == step ? ColorsManager.blackColor : ColorsManager.greyColor, color: isCurrentStep
fontWeight: currentStep == step ? FontWeight.bold : FontWeight.normal, ? ColorsManager.blackColor
: ColorsManager.greyColor,
fontWeight:
isCurrentStep ? FontWeight.bold : FontWeight.normal,
), ),
), ),
], ],

View File

@ -19,6 +19,7 @@ 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/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
class UsersPage extends StatelessWidget { class UsersPage extends StatelessWidget {
UsersPage({super.key}); UsersPage({super.key});
@ -451,8 +452,8 @@ class UsersPage extends StatelessWidget {
), ),
Row( Row(
children: [ children: [
user.isEnabled != false if (user.isEnabled != false)
? actionButton( actionButton(
isActive: true, isActive: true,
title: "Edit", title: "Edit",
onTap: () { onTap: () {
@ -463,19 +464,17 @@ class UsersPage extends StatelessWidget {
context: context, context: context,
barrierDismissible: false, barrierDismissible: false,
builder: (BuildContext context) { builder: (BuildContext context) {
return EditUserDialog( return EditUserDialog(user: user);
userId: user.uuid);
}, },
).then((v) { ).then((v) {
if (v != null) {
if (v != null) { if (v != null) {
_blocRole.add(const GetUsers()); _blocRole.add(const GetUsers());
} }
}
}); });
}, },
) )
: actionButton( else
actionButton(
title: "Edit", title: "Edit",
), ),
actionButton( actionButton(

View File

@ -68,7 +68,7 @@ class VisitorPasswordBloc
DateTime? startTime = DateTime.now(); DateTime? startTime = DateTime.now();
DateTime? endTime; DateTime? endTime;
String startTimeAccess = 'Start Time'; String startTimeAccess = DateTime.now().toString().split('.').first;
String endTimeAccess = 'End Time'; String endTimeAccess = 'End Time';
PasswordStatus? passwordStatus; PasswordStatus? passwordStatus;
selectAccessType( selectAccessType(
@ -136,6 +136,27 @@ class VisitorPasswordBloc
); );
return; return;
} }
if(selectedTimestamp < DateTime.now().millisecondsSinceEpoch ~/ 1000) {
if(selectedTimestamp < DateTime.now().millisecondsSinceEpoch ~/ 1000) {
await showDialog<void>(
context: event.context,
builder: (context) => AlertDialog(
title: const Text('Effective Time cannot be earlier than current time.'),
actionsAlignment: MainAxisAlignment.center,
content:
FilledButton(
onPressed: () {
Navigator.of(event.context).pop();
add(SelectTimeVisitorPassword(context: event.context, isStart: true, isRepeat: false));
},
child: const Text('OK'),
),
),
);
}
return;
}
effectiveTimeTimeStamp = selectedTimestamp; effectiveTimeTimeStamp = selectedTimestamp;
startTimeAccess = selectedDateTime.toString().split('.').first; startTimeAccess = selectedDateTime.toString().split('.').first;
} else { } else {