import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.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/model/password_model.dart'; import 'package:syncrow_web/services/access_mang_api.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/app_enum.dart'; import 'package:syncrow_web/utils/snack_bar.dart'; class AccessBloc extends Bloc { AccessBloc() : super((AccessInitial())) { on(_onFetchTableData); // on(selectFilterTap); on(selectTime); on(_filterData); on(resetSearch); on(onTabChanged); } String startTime = 'Start Date'; String endTime = 'End Date'; int? effectiveTimeTimeStamp; int? expirationTimeTimeStamp; TextEditingController passwordName = TextEditingController(); List filteredData = []; List data = []; Future _onFetchTableData(FetchTableData event, Emitter emit) async { try { emit(AccessLoaded()); data = await AccessMangApi().fetchVisitorPassword(); filteredData = data; updateTabsCount(); emit(TableLoaded(data)); } catch (e) { emit(FailedState(e.toString())); } } void updateTabsCount() { int toBeEffectiveCount = data.where((item) => item.passwordStatus.value == 'To be effective').length; int effectiveCount = data.where((item) => item.passwordStatus.value == 'Effective').length; int expiredCount = data.where((item) => item.passwordStatus.value == 'Expired').length; tabs[1] = 'To Be Effective ($toBeEffectiveCount)'; tabs[2] = 'Effective ($effectiveCount)'; tabs[3] = 'Expired ($expiredCount)'; } int selectedIndex = 0; final List tabs = ['All', 'To Be Effective (0)', 'Effective (0)', 'Expired']; Future selectFilterTap(TabChangedEvent event, Emitter emit) async { try { emit(AccessLoaded()); selectedIndex = event.selectedIndex; emit(AccessInitial()); emit(TableLoaded(data)); } catch (e) { emit(FailedState(e.toString())); return; } } Future selectTime(SelectTime event, Emitter emit) async { emit(AccessLoaded()); final DateTime? picked = await showDatePicker( context: event.context, initialDate: DateTime.now(), firstDate: DateTime(2015, 8), lastDate: DateTime(2101), ); if (picked != null) { final selectedDateTime = DateTime( picked.year, picked.month, picked.day, ); final selectedTimestamp = DateTime( selectedDateTime.year, selectedDateTime.month, selectedDateTime.day, selectedDateTime.hour, selectedDateTime.minute, ).millisecondsSinceEpoch ~/ 1000; // Divide by 1000 to remove milliseconds if (event.isStart) { if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) { CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.'); } else { startTime = selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds effectiveTimeTimeStamp = selectedTimestamp; } } else { if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) { CustomSnackBar.displaySnackBar('Expiration Time cannot be earlier than Effective Time.'); } else { endTime = selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds expirationTimeTimeStamp = selectedTimestamp; } } } emit(ChangeTimeState()); } Future _filterData(FilterDataEvent event, Emitter emit) async { emit(AccessLoaded()); try { filteredData = data.where((item) { 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) { final bool matchesName = item.passwordName != null && item.passwordName.contains(event.passwordName); if (!matchesName) { 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) { DateTime startDateOnly = DateTime.fromMillisecondsSinceEpoch(event.startTime! * 1000).toUtc().toLocal(); DateTime endDateOnly = DateTime.fromMillisecondsSinceEpoch(event.endTime! * 1000).toUtc().toLocal(); startDateOnly = DateTime(startDateOnly.year, startDateOnly.month, startDateOnly.day); endDateOnly = DateTime(endDateOnly.year, endDateOnly.month, endDateOnly.day); if (effectiveDateOnly.isBefore(startDateOnly) || invalidDateOnly.isAfter(endDateOnly)) { 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())); } } resetSearch(ResetSearch event, Emitter emit) async { emit(AccessLoaded()); startTime = 'Start Time'; endTime = 'End Time'; passwordName.clear(); selectedIndex = 0; effectiveTimeTimeStamp = null; expirationTimeTimeStamp = null; add(FetchTableData()); } String timestampToDate(dynamic timestamp) { DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(int.parse(timestamp) * 1000); return "${dateTime.year}/${dateTime.month.toString().padLeft(2, '0')}/${dateTime.day.toString().padLeft(2, '0')}"; } Future onTabChanged(TabChangedEvent event, Emitter emit) async { try { emit(AccessLoaded()); selectedIndex = event.selectedIndex; switch (selectedIndex) { case 0: // All filteredData = data; break; case 1: // To Be Effective filteredData = data.where((item) => item.passwordStatus.value == "To Be Effective").toList(); break; case 2: // Effective filteredData = data.where((item) => item.passwordStatus.value == "Effective").toList(); break; case 3: // Expired filteredData = data.where((item) => item.passwordStatus.value == "Expired").toList(); break; default: filteredData = data; } add(FilterDataEvent( selectedTabIndex: selectedIndex, passwordName: passwordName.text.toLowerCase(), startTime: effectiveTimeTimeStamp, endTime: expirationTimeTimeStamp)); emit(TableLoaded(filteredData)); } catch (e) { emit(FailedState(e.toString())); } } }