Merge branch 'feat/fd-1023' into feat/fd-905
This commit is contained in:
commit
a89edb0ae4
|
@ -59,6 +59,43 @@ class PhpGroup {
|
||||||
static GetResidentsByProperty getResidentsByProperty = GetResidentsByProperty();
|
static GetResidentsByProperty getResidentsByProperty = GetResidentsByProperty();
|
||||||
static GetOpenedVisits getOpenedVisits = GetOpenedVisits();
|
static GetOpenedVisits getOpenedVisits = GetOpenedVisits();
|
||||||
static GetLicense getLicense = GetLicense();
|
static GetLicense getLicense = GetLicense();
|
||||||
|
static GetProvSchedules getProvSchedules = GetProvSchedules();
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetProvSchedules {
|
||||||
|
Future<ApiCallResponse> call(final String page) async {
|
||||||
|
// final String baseUrl = PhpGroup.getBaseUrl();
|
||||||
|
// final String devUUID = (await StorageHelper().g(KeychainStorageKey.devUUID.value)) ?? '';
|
||||||
|
// final String userUUID = (await StorageHelper().g(KeychainStorageKey.userUUID.value)) ?? '';
|
||||||
|
// final String cliID = (await StorageHelper().g(KeychainStorageKey.clientUUID.value)) ?? '';
|
||||||
|
// const String atividade = 'getProvSchedules';
|
||||||
|
// const String pageSize = '10';
|
||||||
|
final String baseUrl = 'http://localhost:3000';
|
||||||
|
return await ApiManager.instance.makeApiCall(
|
||||||
|
callName: 'getProvSchedules',
|
||||||
|
apiUrl: '$baseUrl/getAgendamentoProv.php',
|
||||||
|
callType: ApiCallType.POST,
|
||||||
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||||
|
params: {
|
||||||
|
"proId": "8",
|
||||||
|
"status": "AT",
|
||||||
|
"page": page,
|
||||||
|
"pageSize": "10"
|
||||||
|
// 'devUUID': devUUID,
|
||||||
|
// 'userUUID': userUUID,
|
||||||
|
// 'cliID': cliID,
|
||||||
|
// 'atividade': atividade,
|
||||||
|
// 'page': page,
|
||||||
|
// 'pageSize': pageSize,
|
||||||
|
},
|
||||||
|
bodyType: BodyType.X_WWW_FORM_URL_ENCODED,
|
||||||
|
returnBody: true,
|
||||||
|
encodeBodyUtf8: false,
|
||||||
|
decodeUtf8: false,
|
||||||
|
cache: false,
|
||||||
|
alwaysAllowBody: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GetOpenedVisits {
|
class GetOpenedVisits {
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export 'data_sources/index.dart';
|
||||||
|
export 'repositories/index.dart';
|
||||||
|
export 'models/index.dart';
|
|
@ -0,0 +1,3 @@
|
||||||
|
export 'entities/index.dart';
|
||||||
|
export 'respositories/index.dart';
|
||||||
|
export 'usecases/index.dart';
|
|
@ -0,0 +1,3 @@
|
||||||
|
export 'data/index.dart';
|
||||||
|
export 'domain/index.dart';
|
||||||
|
export 'presentation/index.dart';
|
|
@ -0,0 +1,3 @@
|
||||||
|
export 'blocs/index.dart';
|
||||||
|
export 'pages/index.dart';
|
||||||
|
export 'widgets/index.dart';
|
|
@ -0,0 +1,3 @@
|
||||||
|
export 'data_sources/index.dart';
|
||||||
|
export 'repositories/index.dart';
|
||||||
|
export 'models/index.dart';
|
|
@ -0,0 +1,3 @@
|
||||||
|
export 'entities/index.dart';
|
||||||
|
export 'respositories/index.dart';
|
||||||
|
export 'usecases/index.dart';
|
|
@ -0,0 +1,3 @@
|
||||||
|
export 'data/index.dart';
|
||||||
|
export 'domain/index.dart';
|
||||||
|
export 'presentation/index.dart';
|
|
@ -0,0 +1,117 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:hub/backend/api_requests/api_manager.dart';
|
||||||
|
import 'package:hub/flutter_flow/nav/nav.dart';
|
||||||
|
import 'package:hub/shared/utils/dialog_util.dart';
|
||||||
|
import 'package:hub/shared/utils/log_util.dart';
|
||||||
|
|
||||||
|
class HistoryBloc extends Bloc<HistoryEvent, HistoryState> {
|
||||||
|
final ScrollController scrollController = ScrollController();
|
||||||
|
final Future<ApiCallResponse> Function(int pageSize, int pageNumber, Map<String, String> opt) fetchHistoryService;
|
||||||
|
final bool Function(dynamic item, Map<String, String> opt)? filterLogic;
|
||||||
|
|
||||||
|
HistoryBloc(Map<String, String> opt, this.fetchHistoryService, {this.filterLogic}) : super(HistoryState(opt: opt)) {
|
||||||
|
scrollController.addListener(_onScroll);
|
||||||
|
on<UpdateHistoryEvent>(_onUpdateHistory);
|
||||||
|
on<FetchHistoryEvent>(_onFetchHistory);
|
||||||
|
add(FetchHistoryEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onScroll() {
|
||||||
|
if (scrollController.position.atEdge && scrollController.position.pixels != 0) {
|
||||||
|
add(FetchHistoryEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onUpdateHistory(UpdateHistoryEvent event, Emitter<HistoryState> emit) async {
|
||||||
|
emit(state.copyWith(opt: event.newOpt, historyWrap: [], pageNumber: 1));
|
||||||
|
add(FetchHistoryEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onFetchHistory(FetchHistoryEvent event, Emitter<HistoryState> emit) async {
|
||||||
|
if (state.loading) return;
|
||||||
|
emit(state.copyWith(loading: true));
|
||||||
|
try {
|
||||||
|
var response = await fetchHistoryService(state.pageSize, state.pageNumber, state.opt);
|
||||||
|
|
||||||
|
final List<dynamic> history = response.jsonBody['acessos'] ?? [];
|
||||||
|
List<dynamic> filteredHistory = history.where((item) {
|
||||||
|
if (filterLogic != null) {
|
||||||
|
return filterLogic!(item, state.opt);
|
||||||
|
} else {
|
||||||
|
return true; // Default to no filtering if no logic is provided
|
||||||
|
}
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
if (filteredHistory.isNotEmpty) {
|
||||||
|
emit(state.copyWith(
|
||||||
|
historyWrap: [...state.historyWrap, ...filteredHistory],
|
||||||
|
hasData: true,
|
||||||
|
loading: false,
|
||||||
|
pageNumber: state.pageNumber + 1,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
emit(state.copyWith(hasData: false, loading: false));
|
||||||
|
}
|
||||||
|
} catch (e, s) {
|
||||||
|
await DialogUtil.errorDefault(navigatorKey.currentContext!);
|
||||||
|
LogUtil.requestAPIFailed('processRequest', "", "Fetch History", e, s);
|
||||||
|
emit(state.copyWith(hasData: false, loading: false, error: e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() {
|
||||||
|
scrollController.dispose();
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HistoryState {
|
||||||
|
final Map<String, String> opt;
|
||||||
|
final List<dynamic> historyWrap;
|
||||||
|
final bool hasData;
|
||||||
|
final bool loading;
|
||||||
|
final int pageNumber;
|
||||||
|
final int pageSize;
|
||||||
|
final String? error;
|
||||||
|
|
||||||
|
HistoryState({
|
||||||
|
required this.opt,
|
||||||
|
this.historyWrap = const [],
|
||||||
|
this.hasData = false,
|
||||||
|
this.loading = false,
|
||||||
|
this.pageNumber = 1,
|
||||||
|
this.pageSize = 10,
|
||||||
|
this.error,
|
||||||
|
});
|
||||||
|
|
||||||
|
HistoryState copyWith({
|
||||||
|
Map<String, String>? opt,
|
||||||
|
List<dynamic>? historyWrap,
|
||||||
|
bool? hasData,
|
||||||
|
bool? loading,
|
||||||
|
int? pageNumber,
|
||||||
|
int? pageSize,
|
||||||
|
String? error,
|
||||||
|
}) {
|
||||||
|
return HistoryState(
|
||||||
|
opt: opt ?? this.opt,
|
||||||
|
historyWrap: historyWrap ?? this.historyWrap,
|
||||||
|
hasData: hasData ?? this.hasData,
|
||||||
|
loading: loading ?? this.loading,
|
||||||
|
pageNumber: pageNumber ?? this.pageNumber,
|
||||||
|
pageSize: pageSize ?? this.pageSize,
|
||||||
|
error: error ?? this.error,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class HistoryEvent {}
|
||||||
|
|
||||||
|
class UpdateHistoryEvent extends HistoryEvent {
|
||||||
|
final Map<String, String> newOpt;
|
||||||
|
UpdateHistoryEvent(this.newOpt);
|
||||||
|
}
|
||||||
|
|
||||||
|
class FetchHistoryEvent extends HistoryEvent {}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export 'history_bloc_template.dart';
|
||||||
|
export 'provisional_history_bloc.dart';
|
|
@ -0,0 +1,3 @@
|
||||||
|
export 'blocs/index.dart';
|
||||||
|
export 'pages/index.dart';
|
||||||
|
export 'widgets/index.dart';
|
|
@ -0,0 +1,106 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:hub/backend/api_requests/api_calls.dart';
|
||||||
|
import 'package:hub/components/molecular_components/message_opt_modal/opt_modal_widget.dart';
|
||||||
|
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
|
||||||
|
import 'package:hub/features/history/index.dart';
|
||||||
|
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
|
||||||
|
import 'package:hub/flutter_flow/internationalization.dart';
|
||||||
|
import 'package:hub/shared/helpers/storage/base_storage.dart';
|
||||||
|
import 'package:hub/shared/helpers/storage/storage_helper.dart';
|
||||||
|
|
||||||
|
class AcessCubit extends Cubit<String?> {
|
||||||
|
AcessCubit() : super('Provisional');
|
||||||
|
|
||||||
|
Future<void> fetchCliUUID() async {
|
||||||
|
final cliUUID = await StorageHelper().get(KeychainStorageKey.clientUUID.value);
|
||||||
|
emit(cliUUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ApiCallResponse> fetchHistoryService(int pageSize, int pageNumber, Map<String, String> opt) async {
|
||||||
|
return await PhpGroup.getAccessCall.call(
|
||||||
|
pageSize: pageSize.toString(),
|
||||||
|
pageNumber: pageNumber.toString(),
|
||||||
|
pesTipo: opt['personType'] != 'E' && opt['personType'] != 'O' ? 'T' : opt['personType'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool filterLogic(dynamic item, Map<String, String> opt) {
|
||||||
|
final personTypeMatches = opt['personType'] == '.*' || item["PES_TIPO"].toString() == opt['personType'];
|
||||||
|
return personTypeMatches;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccessHistoryPage extends StatelessWidget {
|
||||||
|
final Map<String, String> opt = {
|
||||||
|
'personType': '.*',
|
||||||
|
'accessType': '.*',
|
||||||
|
'search': '.*',
|
||||||
|
};
|
||||||
|
|
||||||
|
final String appBarTitle = 'Histórico Provisório';
|
||||||
|
final String noHistoryMessage = 'Nenhum histórico encontrado!';
|
||||||
|
final String errorMessage = 'Falha ao realizar operação!';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => AcessCubit()..fetchCliUUID(),
|
||||||
|
child: HistoryPageTemplate(
|
||||||
|
opt: opt,
|
||||||
|
fetchHistoryService: (pageSize, pageNumber, opt) => context.read<AcessCubit>().fetchHistoryService(pageSize, pageNumber, opt),
|
||||||
|
cardBuilder: cardBuilder,
|
||||||
|
appBarTitle: appBarTitle,
|
||||||
|
noHistoryMessage: noHistoryMessage,
|
||||||
|
errorMessage: errorMessage,
|
||||||
|
isLeading: true,
|
||||||
|
isFilter: true,
|
||||||
|
filterLogic: (item, opt) => context.read<AcessCubit>().filterLogic(item, opt),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardBuilder(BuildContext context, dynamic historyItem) {
|
||||||
|
final cliUUID = context.watch<AcessCubit>().state;
|
||||||
|
final String imagePath = 'https://freaccess.com.br/freaccess/getImage.php?cliID=${cliUUID}&atividade=getFoto&Documento=${historyItem['PES_ID'] ?? ''}&tipo=${historyItem['PES_TIPO'] ?? ''}';
|
||||||
|
final Map<String, String> labelsHashMap = {
|
||||||
|
FFLocalizations.of(context).getVariableText(ptText: 'Nome:', enText: 'Name:'): historyItem['PES_NOME'] ?? '',
|
||||||
|
FFLocalizations.of(context).getVariableText(ptText: 'Acesso:', enText: 'Access:'): historyItem['ACE_DATAHORA'] ?? '',
|
||||||
|
FFLocalizations.of(context).getVariableText(ptText: 'Setor', enText: 'Sector'): historyItem['SET_DESCRICAO'] ?? '',
|
||||||
|
};
|
||||||
|
|
||||||
|
final statusHashMap = [
|
||||||
|
_getPersonTypeStatus(context, historyItem['PES_TIPO']),
|
||||||
|
_getAccessTypeStatus(context, historyItem['ACE_TIPO']),
|
||||||
|
];
|
||||||
|
|
||||||
|
return CardItemTemplateComponentWidget(
|
||||||
|
imagePath: imagePath,
|
||||||
|
labelsHashMap: labelsHashMap,
|
||||||
|
statusHashMap: statusHashMap,
|
||||||
|
onTapCardItemAction: () async {},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Color> _getPersonTypeStatus(BuildContext context, String? personType) {
|
||||||
|
switch (personType) {
|
||||||
|
case 'O':
|
||||||
|
return {FFLocalizations.of(context).getVariableText(ptText: 'Morador', enText: 'Resident'): FlutterFlowTheme.of(context).alternate2};
|
||||||
|
case 'E':
|
||||||
|
return {FFLocalizations.of(context).getVariableText(ptText: 'Visitante', enText: 'Visitor'): FlutterFlowTheme.of(context).alternate2};
|
||||||
|
default:
|
||||||
|
return {FFLocalizations.of(context).getVariableText(ptText: 'Desconhecido', enText: 'Unknown'): FlutterFlowTheme.of(context).alternate2};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Color> _getAccessTypeStatus(BuildContext context, String? accessType) {
|
||||||
|
switch (accessType) {
|
||||||
|
case '0':
|
||||||
|
return {FFLocalizations.of(context).getVariableText(ptText: 'Entrada', enText: 'Entrance'): FlutterFlowTheme.of(context).success};
|
||||||
|
case '1':
|
||||||
|
return {FFLocalizations.of(context).getVariableText(ptText: 'Saída', enText: 'Exit'): FlutterFlowTheme.of(context).error};
|
||||||
|
default:
|
||||||
|
return {FFLocalizations.of(context).getVariableText(ptText: 'Desconhecido', enText: 'Unknown'): FlutterFlowTheme.of(context).warning};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,211 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'package:hub/features/history/index.dart';
|
||||||
|
import 'package:hub/flutter_flow/internationalization.dart';
|
||||||
|
import 'package:hub/flutter_flow/nav/nav.dart';
|
||||||
|
import 'package:hub/backend/api_requests/api_manager.dart';
|
||||||
|
import 'package:hub/features/history/presentation/widgets/filter_modal.dart';
|
||||||
|
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
|
||||||
|
import 'package:hub/shared/utils/dialog_util.dart';
|
||||||
|
import 'package:hub/shared/utils/log_util.dart';
|
||||||
|
import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
|
||||||
|
|
||||||
|
class HistoryPageTemplate extends StatelessWidget {
|
||||||
|
final Map<String, String> opt;
|
||||||
|
final Future<ApiCallResponse> Function(int pageSize, int pageNumber, Map<String, String> opt) fetchHistoryService;
|
||||||
|
final Widget Function(BuildContext context, dynamic historyItem) cardBuilder;
|
||||||
|
final String appBarTitle;
|
||||||
|
final String noHistoryMessage;
|
||||||
|
final String errorMessage;
|
||||||
|
final bool isLeading;
|
||||||
|
final bool isFilter;
|
||||||
|
final bool Function(dynamic item, Map<String, String> opt)? filterLogic;
|
||||||
|
|
||||||
|
const HistoryPageTemplate({
|
||||||
|
Key? key,
|
||||||
|
required this.opt,
|
||||||
|
required this.fetchHistoryService,
|
||||||
|
required this.cardBuilder,
|
||||||
|
this.appBarTitle = 'History',
|
||||||
|
this.noHistoryMessage = 'No history found!',
|
||||||
|
this.errorMessage = 'Failed to perform operation!',
|
||||||
|
this.isLeading = true,
|
||||||
|
this.isFilter = false,
|
||||||
|
this.filterLogic,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => HistoryBloc(opt, fetchHistoryService, filterLogic: filterLogic),
|
||||||
|
child: HistoryPageView(
|
||||||
|
cardBuilder: cardBuilder,
|
||||||
|
appBarTitle: appBarTitle,
|
||||||
|
noHistoryMessage: noHistoryMessage,
|
||||||
|
errorMessage: errorMessage,
|
||||||
|
isLeading: isLeading,
|
||||||
|
isFilter: isFilter,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HistoryPageView extends StatelessWidget {
|
||||||
|
final Widget Function(BuildContext context, dynamic historyItem) cardBuilder;
|
||||||
|
final String appBarTitle;
|
||||||
|
final String noHistoryMessage;
|
||||||
|
final String errorMessage;
|
||||||
|
final bool isLeading;
|
||||||
|
final bool isFilter;
|
||||||
|
|
||||||
|
const HistoryPageView({
|
||||||
|
Key? key,
|
||||||
|
required this.cardBuilder,
|
||||||
|
required this.appBarTitle,
|
||||||
|
required this.noHistoryMessage,
|
||||||
|
required this.errorMessage,
|
||||||
|
this.isLeading = false,
|
||||||
|
this.isFilter = false,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = FlutterFlowTheme.of(context);
|
||||||
|
return Scaffold(
|
||||||
|
key: GlobalKey<ScaffoldState>(),
|
||||||
|
backgroundColor: theme.primaryBackground,
|
||||||
|
appBar: _buildAppBar(context, theme),
|
||||||
|
body: _buildBody(context),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PreferredSizeWidget _buildAppBar(BuildContext context, FlutterFlowTheme theme) {
|
||||||
|
return AppBar(
|
||||||
|
backgroundColor: theme.primaryBackground,
|
||||||
|
automaticallyImplyLeading: false,
|
||||||
|
leading: isLeading ? _buildBackButton(context, theme) : null,
|
||||||
|
title: _buildTitle(context, theme),
|
||||||
|
centerTitle: true,
|
||||||
|
elevation: 0.0,
|
||||||
|
actions: [
|
||||||
|
if (isFilter) _buildFilterButton(context),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildBackButton(BuildContext context, FlutterFlowTheme theme) {
|
||||||
|
return FlutterFlowIconButton(
|
||||||
|
borderColor: Colors.transparent,
|
||||||
|
borderRadius: 30.0,
|
||||||
|
borderWidth: 1.0,
|
||||||
|
buttonSize: 60.0,
|
||||||
|
icon: Icon(
|
||||||
|
Icons.keyboard_arrow_left,
|
||||||
|
color: theme.primaryText,
|
||||||
|
size: 30.0,
|
||||||
|
),
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTitle(BuildContext context, FlutterFlowTheme theme) {
|
||||||
|
return Text(
|
||||||
|
appBarTitle,
|
||||||
|
style: theme.headlineMedium.override(
|
||||||
|
fontFamily: theme.headlineMediumFamily,
|
||||||
|
color: theme.primaryText,
|
||||||
|
fontSize: 16.0,
|
||||||
|
letterSpacing: 0.0,
|
||||||
|
useGoogleFonts: GoogleFonts.asMap().containsKey(theme.headlineMediumFamily),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildFilterButton(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(0, 0, 10, 0),
|
||||||
|
child: IconButton(
|
||||||
|
icon: const Icon(Icons.filter_list),
|
||||||
|
onPressed: () async {
|
||||||
|
final Map<String, String>? selectedFilter = await showModalBottomSheet<Map<String, String>>(
|
||||||
|
isScrollControlled: true,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext bottomSheetContext) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () => Navigator.of(bottomSheetContext).pop(),
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {},
|
||||||
|
child: FilterModalWidget(
|
||||||
|
defaultSelections: {
|
||||||
|
'personType': context.read<HistoryBloc>().state.opt['personType'] == '.*' ? ['E', 'O'] : [context.read<HistoryBloc>().state.opt['personType']],
|
||||||
|
'search': '.*',
|
||||||
|
},
|
||||||
|
filterOptions: {
|
||||||
|
'personType': [
|
||||||
|
{'title': FFLocalizations.of(context).getVariableText(ptText: 'Visitante', enText: 'Visitor'), 'value': 'E',},
|
||||||
|
{'title': FFLocalizations.of(context).getVariableText(ptText: 'Morador', enText: 'Resident'), 'value': 'O',},
|
||||||
|
|
||||||
|
],
|
||||||
|
},
|
||||||
|
filterTitles: {
|
||||||
|
'personType': 'Person Type',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (selectedFilter != null) {
|
||||||
|
context.read<HistoryBloc>().add(UpdateHistoryEvent(selectedFilter));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildBody(BuildContext context) {
|
||||||
|
return BlocBuilder<HistoryBloc, HistoryState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
if (state.loading && state.historyWrap.isEmpty) {
|
||||||
|
return Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
valueColor: AlwaysStoppedAnimation<Color>(
|
||||||
|
FlutterFlowTheme.of(context).primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (state.error != null) {
|
||||||
|
return Center(
|
||||||
|
child: Text(errorMessage),
|
||||||
|
);
|
||||||
|
} else if (state.historyWrap.isEmpty) {
|
||||||
|
return Center(
|
||||||
|
child: Text(noHistoryMessage),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const BouncingScrollPhysics(),
|
||||||
|
controller: context.read<HistoryBloc>().scrollController,
|
||||||
|
itemCount: state.historyWrap.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final historyItem = state.historyWrap[index];
|
||||||
|
return cardBuilder(context, historyItem);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
export 'history_page_template.dart';
|
||||||
|
export 'provisional_history_page.dart';
|
|
@ -0,0 +1,105 @@
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:hub/backend/api_requests/api_calls.dart';
|
||||||
|
import 'package:hub/components/molecular_components/message_opt_modal/opt_modal_widget.dart';
|
||||||
|
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
|
||||||
|
import 'package:hub/features/history/index.dart';
|
||||||
|
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
|
||||||
|
import 'package:hub/flutter_flow/internationalization.dart';
|
||||||
|
import 'package:hub/shared/helpers/storage/base_storage.dart';
|
||||||
|
import 'package:hub/shared/helpers/storage/storage_helper.dart';
|
||||||
|
|
||||||
|
class ProvisionalCubit extends Cubit<String?> {
|
||||||
|
ProvisionalCubit() : super('Provisional');
|
||||||
|
|
||||||
|
Future<void> fetchCliUUID() async {
|
||||||
|
final cliUUID = await StorageHelper().get(KeychainStorageKey.clientUUID.value);
|
||||||
|
emit(cliUUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ApiCallResponse> fetchHistoryService(int pageSize, int pageNumber, Map<String, String> status) async {
|
||||||
|
return await PhpGroup.getProvSchedules(pageNumber.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool filterLogic(dynamic item, Map<String, String> opt) {
|
||||||
|
final personTypeMatches = opt['personType'] == '.*' || item["PES_TIPO"].toString() == opt['personType'];
|
||||||
|
return personTypeMatches;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProvisionalHistoryPage extends StatelessWidget {
|
||||||
|
final Map<String, String> opt = {
|
||||||
|
'personType': '.*',
|
||||||
|
'accessType': '.*',
|
||||||
|
'search': '.*',
|
||||||
|
};
|
||||||
|
|
||||||
|
final String appBarTitle = 'Histórico Provisório';
|
||||||
|
final String noHistoryMessage = 'Nenhum histórico encontrado!';
|
||||||
|
final String errorMessage = 'Falha ao realizar operação!';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => ProvisionalCubit()..fetchCliUUID(),
|
||||||
|
child: HistoryPageTemplate(
|
||||||
|
opt: opt,
|
||||||
|
fetchHistoryService: (pageSize, pageNumber, opt) => context.read<ProvisionalCubit>().fetchHistoryService(pageSize, pageNumber, opt),
|
||||||
|
cardBuilder: cardBuilder,
|
||||||
|
appBarTitle: appBarTitle,
|
||||||
|
noHistoryMessage: noHistoryMessage,
|
||||||
|
errorMessage: errorMessage,
|
||||||
|
isLeading: true,
|
||||||
|
isFilter: false,
|
||||||
|
filterLogic: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardBuilder(BuildContext context, dynamic historyItem) {
|
||||||
|
log('historyItem: $historyItem');
|
||||||
|
final cliUUID = context.watch<ProvisionalCubit>().state;
|
||||||
|
final String imagePath = 'https://freaccess.com.br/freaccess/getImage.php?cliID=${cliUUID}&atividade=getFoto&Documento=${historyItem['PES_ID'] ?? ''}&tipo=${historyItem['PES_TIPO'] ?? ''}';
|
||||||
|
final Map<String, String> labelsHashMap = {
|
||||||
|
FFLocalizations.of(context).getVariableText(ptText: 'Nome:', enText: 'Name:'): historyItem['PES_NOME'] ?? '',
|
||||||
|
FFLocalizations.of(context).getVariableText(ptText: 'Acesso:', enText: 'Access:'): historyItem['ACE_DATAHORA'] ?? '',
|
||||||
|
FFLocalizations.of(context).getVariableText(ptText: 'Setor', enText: 'Sector'): historyItem['SET_DESCRICAO'] ?? '',
|
||||||
|
};
|
||||||
|
|
||||||
|
final statusHashMap = [
|
||||||
|
_getPersonTypeStatus(context, historyItem['PES_TIPO']),
|
||||||
|
_getAccessTypeStatus(context, historyItem['ACE_TIPO']),
|
||||||
|
];
|
||||||
|
|
||||||
|
return CardItemTemplateComponentWidget(
|
||||||
|
imagePath: imagePath,
|
||||||
|
labelsHashMap: labelsHashMap,
|
||||||
|
statusHashMap: statusHashMap,
|
||||||
|
onTapCardItemAction: () async {},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Color> _getPersonTypeStatus(BuildContext context, String? personType) {
|
||||||
|
switch (personType) {
|
||||||
|
case 'O':
|
||||||
|
return {FFLocalizations.of(context).getVariableText(ptText: 'Morador', enText: 'Resident'): FlutterFlowTheme.of(context).alternate2};
|
||||||
|
case 'E':
|
||||||
|
return {FFLocalizations.of(context).getVariableText(ptText: 'Visitante', enText: 'Visitor'): FlutterFlowTheme.of(context).alternate2};
|
||||||
|
default:
|
||||||
|
return {FFLocalizations.of(context).getVariableText(ptText: 'Desconhecido', enText: 'Unknown'): FlutterFlowTheme.of(context).alternate2};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Color> _getAccessTypeStatus(BuildContext context, String? accessType) {
|
||||||
|
switch (accessType) {
|
||||||
|
case '0':
|
||||||
|
return {FFLocalizations.of(context).getVariableText(ptText: 'Entrada', enText: 'Entrance'): FlutterFlowTheme.of(context).success};
|
||||||
|
case '1':
|
||||||
|
return {FFLocalizations.of(context).getVariableText(ptText: 'Saída', enText: 'Exit'): FlutterFlowTheme.of(context).error};
|
||||||
|
default:
|
||||||
|
return {FFLocalizations.of(context).getVariableText(ptText: 'Desconhecido', enText: 'Unknown'): FlutterFlowTheme.of(context).warning};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,229 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '/flutter_flow/flutter_flow_util.dart';
|
||||||
|
import '/flutter_flow/form_field_controller.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
|
||||||
|
import 'package:hub/flutter_flow/nav/nav.dart';
|
||||||
|
import 'package:hub/shared/utils/limited_text_size.dart';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class FilterModal extends FlutterFlowModel<FilterModalWidget> {
|
||||||
|
FocusNode? textFieldFocusNode;
|
||||||
|
TextEditingController? textController;
|
||||||
|
String? Function(BuildContext, String?)? textControllerValidator;
|
||||||
|
bool? checkboxValue1;
|
||||||
|
bool? checkboxValue2;
|
||||||
|
FormFieldController<List<String>>? checkboxGroupValueController;
|
||||||
|
List<String>? get checkboxGroupValues => checkboxGroupValueController?.value;
|
||||||
|
set checkboxGroupValues(List<String>? v) => checkboxGroupValueController?.value = v;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState(BuildContext context) {}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
textFieldFocusNode?.dispose();
|
||||||
|
textController?.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FilterModalWidget extends StatefulWidget {
|
||||||
|
final Map<String, dynamic> defaultSelections;
|
||||||
|
final Map<String, List<Map<String, String>>> filterOptions;
|
||||||
|
final Map<String, String> filterTitles;
|
||||||
|
|
||||||
|
const FilterModalWidget({
|
||||||
|
super.key,
|
||||||
|
required this.defaultSelections,
|
||||||
|
required this.filterOptions,
|
||||||
|
required this.filterTitles,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_FilterModalWidgetState createState() => _FilterModalWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FilterModalWidgetState extends State<FilterModalWidget> {
|
||||||
|
late FilterModal _model;
|
||||||
|
late Map<String, dynamic> selected;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void setState(VoidCallback callback) {
|
||||||
|
super.setState(callback);
|
||||||
|
_model.onUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
_model = createModel(context, () => FilterModal());
|
||||||
|
|
||||||
|
_model.textController ??= TextEditingController();
|
||||||
|
_model.textFieldFocusNode ??= FocusNode();
|
||||||
|
|
||||||
|
selected = widget.defaultSelections;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _applyFilter() {
|
||||||
|
Map<String, String> filterResult = {
|
||||||
|
'search': _model.textController?.text == '' ? '.*' : _model.textController!.text.toLowerCase(),
|
||||||
|
};
|
||||||
|
|
||||||
|
widget.filterOptions.forEach((key, options) {
|
||||||
|
filterResult[key] = selected[key]!.isEmpty || selected[key]!.length > 1
|
||||||
|
? '.*'
|
||||||
|
: selected[key]!.first;
|
||||||
|
});
|
||||||
|
|
||||||
|
context.pop(filterResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildCheckboxListTile(String key, List<Map<String, String>> options, double fontsize) {
|
||||||
|
double limitedInputFontSize = LimitedFontSizeUtil.getInputFontSize(context);
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.fromSTEB(0.0, 3.0, 0.0, 0.0),
|
||||||
|
child: Text(
|
||||||
|
widget.filterTitles[key]!,
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
style: FlutterFlowTheme.of(context).bodyMedium.override(
|
||||||
|
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
|
||||||
|
fontSize: limitedInputFontSize,
|
||||||
|
letterSpacing: 0.0,
|
||||||
|
useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily),
|
||||||
|
color: FlutterFlowTheme.of(context).primaryText,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
ListView.builder(
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount: options.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final option = options[index];
|
||||||
|
return CheckboxListTile(
|
||||||
|
title: Text(
|
||||||
|
option['title']!,
|
||||||
|
style: FlutterFlowTheme.of(context).bodyMedium.override(
|
||||||
|
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
|
||||||
|
letterSpacing: 0.0,
|
||||||
|
fontSize: limitedInputFontSize,
|
||||||
|
useGoogleFonts: GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily),
|
||||||
|
color: FlutterFlowTheme.of(context).primaryText,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dense: true,
|
||||||
|
value: selected[key]!.contains(option['value']),
|
||||||
|
onChanged: (bool? value) {
|
||||||
|
setState(() {
|
||||||
|
if (value == true) {
|
||||||
|
if (!selected[key]!.contains(option['value'])) {
|
||||||
|
selected[key]!.add(option['value']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
selected[key]!.remove(option['value']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
activeColor: FlutterFlowTheme.of(context).primary,
|
||||||
|
checkColor: FlutterFlowTheme.of(context).info,
|
||||||
|
checkboxShape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(100),
|
||||||
|
),
|
||||||
|
enableFeedback: true,
|
||||||
|
side: BorderSide(
|
||||||
|
width: 5,
|
||||||
|
color: FlutterFlowTheme.of(context).secondaryText,
|
||||||
|
),
|
||||||
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
double screenWidth = MediaQuery.of(context).size.width;
|
||||||
|
|
||||||
|
return Center(
|
||||||
|
child: Container(
|
||||||
|
width: screenWidth - (screenWidth * 0.35),
|
||||||
|
height: 250,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: FlutterFlowTheme.of(context).primaryBackground,
|
||||||
|
borderRadius: BorderRadius.circular(24.0),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(4.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.fromSTEB(10.0, 10.0, 0.0, 10.0),
|
||||||
|
child: Text(
|
||||||
|
FFLocalizations.of(context).getText('yfj9pd6k'),
|
||||||
|
style: FlutterFlowTheme.of(context).headlineMedium.override(
|
||||||
|
fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily,
|
||||||
|
color: FlutterFlowTheme.of(context).primaryText,
|
||||||
|
fontSize: LimitedFontSizeUtil.getHeaderFontSize(context),
|
||||||
|
letterSpacing: 0.0,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
useGoogleFonts:
|
||||||
|
GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).headlineMediumFamily),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: widget.filterOptions.keys.map((key) {
|
||||||
|
return _buildCheckboxListTile(key, widget.filterOptions[key]!, 14);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: _applyFilter,
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
foregroundColor: FlutterFlowTheme.of(context).info,
|
||||||
|
backgroundColor: FlutterFlowTheme.of(context).primary,
|
||||||
|
),
|
||||||
|
child: Text(FFLocalizations.of(context).getText('88kshkph'),
|
||||||
|
style: FlutterFlowTheme.of(context).bodyMedium.override(
|
||||||
|
fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
|
||||||
|
color: FlutterFlowTheme.of(context).info,
|
||||||
|
fontSize: LimitedFontSizeUtil.getInputFontSize(context),
|
||||||
|
letterSpacing: 0.0,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
useGoogleFonts:
|
||||||
|
GoogleFonts.asMap().containsKey(FlutterFlowTheme.of(context).bodyMediumFamily),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export 'filter_modal.dart';
|
|
@ -4,6 +4,7 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hub/backend/schema/util/schema_util.dart';
|
import 'package:hub/backend/schema/util/schema_util.dart';
|
||||||
|
import 'package:hub/features/history/presentation/pages/provisional_history_page.dart';
|
||||||
import 'package:hub/features/home/index.dart';
|
import 'package:hub/features/home/index.dart';
|
||||||
import 'package:hub/features/property/index.dart';
|
import 'package:hub/features/property/index.dart';
|
||||||
import 'package:hub/flutter_flow/flutter_flow_util.dart';
|
import 'package:hub/flutter_flow/flutter_flow_util.dart';
|
||||||
|
@ -130,7 +131,7 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) {
|
||||||
FFRoute(name: 'petsOnThePropertyPage', path: '/petsOnThePropertyPage', builder: (context, params) => Scaffold(body: const PetsHistoryScreen(isApp: true))),
|
FFRoute(name: 'petsOnThePropertyPage', path: '/petsOnThePropertyPage', builder: (context, params) => Scaffold(body: const PetsHistoryScreen(isApp: true))),
|
||||||
FFRoute(name: 'vehiclesOnThePropertyPage', path: '/vehiclesOnThePropertyPage', builder: (context, params) => const VehicleOnTheProperty()),
|
FFRoute(name: 'vehiclesOnThePropertyPage', path: '/vehiclesOnThePropertyPage', builder: (context, params) => const VehicleOnTheProperty()),
|
||||||
FFRoute(name: 'receptionPage', path: '/receptionPage', builder: (context, params) => const ReceptionPageWidget()),
|
FFRoute(name: 'receptionPage', path: '/receptionPage', builder: (context, params) => const ReceptionPageWidget()),
|
||||||
FFRoute(name: 'messageHistoryPage', path: '/messageHistoryPage', builder: (context, params) => const MessageHistoryPageWidget()),
|
FFRoute(name: 'messageHistoryPage', path: '/messageHistoryPage', builder: (context, params) => ProvisionalHistoryPage()),
|
||||||
FFRoute(name: 'registerVisitorPage', path: '/registerVisitorPage', builder: (context, params) => const RegisterVisitorPageWidget()),
|
FFRoute(name: 'registerVisitorPage', path: '/registerVisitorPage', builder: (context, params) => const RegisterVisitorPageWidget()),
|
||||||
FFRoute(name: 'scheduleCompleteVisitPage', path: '/scheduleCompleteVisitPage', builder: (context, params) => const ScheduleCompleteVisitPageWidget()),
|
FFRoute(name: 'scheduleCompleteVisitPage', path: '/scheduleCompleteVisitPage', builder: (context, params) => const ScheduleCompleteVisitPageWidget()),
|
||||||
FFRoute(name: 'deliverySchedule', path: '/deliverySchedule', builder: (context, params) => const DeliverySchedule()),
|
FFRoute(name: 'deliverySchedule', path: '/deliverySchedule', builder: (context, params) => const DeliverySchedule()),
|
||||||
|
|
|
@ -169,8 +169,7 @@ class _AppState extends State<App> {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
|
||||||
FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
|
FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
|
||||||
_appStateNotifier = AppStateNotifier.instance;
|
_appStateNotifier = AppStateNotifier.instance;
|
||||||
_router = createRouter(_appStateNotifier);
|
_router = createRouter(_appStateNotifier);
|
||||||
|
|
|
@ -77,7 +77,8 @@ class LocalsRepositoryImpl implements LocalsRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> unlinkLocal(BuildContext context) {
|
Future<void> unlinkLocal(BuildContext context) async {
|
||||||
return remoteDataSource.detachLocal(context);
|
await remoteDataSource.detachLocal(context);
|
||||||
|
await select(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ class LocalUtil {
|
||||||
await StorageHelper().set(KeychainStorageKey.petAmount.value,
|
await StorageHelper().set(KeychainStorageKey.petAmount.value,
|
||||||
jsonBody['petAmountRegister']?.toString().isEmpty ?? true ? '0' : jsonBody['petAmountRegister'].toString());
|
jsonBody['petAmountRegister']?.toString().isEmpty ?? true ? '0' : jsonBody['petAmountRegister'].toString());
|
||||||
await StorageHelper().set(KeychainStorageKey.userName.value, jsonBody['visitado']['VDO_NOME'] ?? '');
|
await StorageHelper().set(KeychainStorageKey.userName.value, jsonBody['visitado']['VDO_NOME'] ?? '');
|
||||||
|
await StorageHelper().set(KeychainStorageKey.userEmail.value, jsonBody['visitado']['VDO_EMAIL'] ?? '');
|
||||||
|
|
||||||
final bool isNewVersion = jsonBody['newVersion'] ?? false;
|
final bool isNewVersion = jsonBody['newVersion'] ?? false;
|
||||||
await StorageHelper().set(KeychainStorageKey.isNewVersion.value, isNewVersion);
|
await StorageHelper().set(KeychainStorageKey.isNewVersion.value, isNewVersion);
|
||||||
|
|
|
@ -82,7 +82,6 @@ class LicenseLocalDataSourceImpl implements LicenseLocalDataSource {
|
||||||
@override
|
@override
|
||||||
Future<void> clear() async {
|
Future<void> clear() async {
|
||||||
await DatabaseStorage.database.delete(tableLicense);
|
await DatabaseStorage.database.delete(tableLicense);
|
||||||
await DatabaseStorage.database.rawDelete(
|
|
||||||
'DELETE FROM sqlite_sequence WHERE name = "$tableLicense"');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,7 @@ class DatabaseStorage {
|
||||||
onUpgrade: _onUpgrade,
|
onUpgrade: _onUpgrade,
|
||||||
onDowngrade: _onDowngrade,
|
onDowngrade: _onDowngrade,
|
||||||
onOpen: _onOpen,
|
onOpen: _onOpen,
|
||||||
onConfigure: _onConfigure,
|
onConfigure: _onConfigure,
|
||||||
singleInstance: true,
|
|
||||||
);
|
);
|
||||||
await LicenseRepositoryImpl().updateLicense();
|
await LicenseRepositoryImpl().updateLicense();
|
||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
|
@ -62,7 +61,7 @@ class DatabaseStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onDowngrade(Database database, int oldVersion, int newVersion) async {
|
Future<void> _onDowngrade(Database database, int oldVersion, int newVersion) async {
|
||||||
print('Downgrading database from version $oldVersion to $newVersion...');
|
print('Downgrading database from version $oldVersion to $newVersion...');
|
||||||
if (oldVersion >= 2 && newVersion < 2) {
|
if (oldVersion >= 2 && newVersion < 2) {
|
||||||
await _dropTables(database);
|
await _dropTables(database);
|
||||||
}
|
}
|
||||||
|
@ -70,9 +69,9 @@ class DatabaseStorage {
|
||||||
|
|
||||||
Future<void> _executePragmas(Database database) async {
|
Future<void> _executePragmas(Database database) async {
|
||||||
// await database.execute('PRAGMA journal_mode = WAL;');
|
// await database.execute('PRAGMA journal_mode = WAL;');
|
||||||
await database.execute('PRAGMA synchronous = NORMAL;');
|
// await database.execute('PRAGMA synchronous = NORMAL;');
|
||||||
await database.execute('PRAGMA temp_store = MEMORY;');
|
// await database.execute('PRAGMA temp_store = MEMORY;');
|
||||||
await database.execute('PRAGMA foreign_keys = ON;');
|
// await database.execute('PRAGMA foreign_keys = ON;');
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _createTables(Database database, int version) async {
|
Future<void> _createTables(Database database, int version) async {
|
||||||
|
|
|
@ -79,6 +79,7 @@ enum KeychainStorageKey {
|
||||||
userDevUUID,
|
userDevUUID,
|
||||||
status,
|
status,
|
||||||
userName,
|
userName,
|
||||||
|
userEmail,
|
||||||
clientUUID,
|
clientUUID,
|
||||||
ownerName,
|
ownerName,
|
||||||
ownerUUID,
|
ownerUUID,
|
||||||
|
@ -100,6 +101,8 @@ enum KeychainStorageKey {
|
||||||
extension KeychainStorageKeyExtension on KeychainStorageKey {
|
extension KeychainStorageKeyExtension on KeychainStorageKey {
|
||||||
String get value {
|
String get value {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
|
case KeychainStorageKey.userEmail:
|
||||||
|
return 'fre_userEmail';
|
||||||
case KeychainStorageKey.devUUID:
|
case KeychainStorageKey.devUUID:
|
||||||
return 'fre_devUUID';
|
return 'fre_devUUID';
|
||||||
case KeychainStorageKey.userUUID:
|
case KeychainStorageKey.userUUID:
|
||||||
|
|
|
@ -59,8 +59,7 @@ class KeychainHelper implements BaseStorage {
|
||||||
Future<void> clearAll() async {
|
Future<void> clearAll() async {
|
||||||
try {
|
try {
|
||||||
await DatabaseStorage.database.delete(tableKeychain);
|
await DatabaseStorage.database.delete(tableKeychain);
|
||||||
await DatabaseStorage.database.rawDelete(
|
|
||||||
'DELETE FROM sqlite_sequence WHERE name = "$tableKeychain"');
|
|
||||||
|
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
log('() => clearAll keychain: $e', stackTrace: s);
|
log('() => clearAll keychain: $e', stackTrace: s);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:hub/shared/helpers/storage/base_storage.dart';
|
import 'package:hub/shared/helpers/storage/base_storage.dart';
|
||||||
|
|
||||||
|
@ -23,7 +25,12 @@ class SecureStorage implements BaseStorage {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> set<T>(String key, T value) async {
|
Future<void> set<T>(String key, T value) async {
|
||||||
await _secureStorage.write(key: key, value: value.toString());
|
log('Setting value: $value');
|
||||||
|
try {
|
||||||
|
await _secureStorage.write(key: key, value: value.toString());
|
||||||
|
} catch (e, s) {
|
||||||
|
log('Error setting value: $e', stackTrace: s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -33,6 +40,15 @@ class SecureStorage implements BaseStorage {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> clearAll() async {
|
Future<void> clearAll() async {
|
||||||
await _secureStorage.deleteAll();
|
log('Clearing SecureStorage');
|
||||||
|
try{
|
||||||
|
await _secureStorage.deleteAll(
|
||||||
|
aOptions: AndroidOptions(),
|
||||||
|
iOptions: IOSOptions(),
|
||||||
|
);
|
||||||
|
} catch (e, s) {
|
||||||
|
log('Error clearing all: $e', stackTrace: s);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:hub/features/home/presentation/pages/home_page.dart';
|
import 'package:hub/features/home/presentation/pages/home_page.dart';
|
||||||
import 'package:hub/flutter_flow/nav/nav.dart';
|
import 'package:hub/flutter_flow/nav/nav.dart';
|
||||||
import 'package:hub/shared/components/molecules/modules/data/repositories/license_repository_impl.dart';
|
import 'package:hub/shared/components/molecules/modules/data/repositories/license_repository_impl.dart';
|
||||||
|
@ -14,6 +15,8 @@ import '../../../backend/api_requests/api_calls.dart';
|
||||||
import '../../../flutter_flow/flutter_flow_util.dart';
|
import '../../../flutter_flow/flutter_flow_util.dart';
|
||||||
import '../../../flutter_flow/random_data_util.dart';
|
import '../../../flutter_flow/random_data_util.dart';
|
||||||
import '../../components/molecules/locals/data/index.dart';
|
import '../../components/molecules/locals/data/index.dart';
|
||||||
|
import '../../components/molecules/locals/index.dart';
|
||||||
|
import '../../components/molecules/menu/index.dart';
|
||||||
import '../../utils/device_util.dart';
|
import '../../utils/device_util.dart';
|
||||||
import '../../utils/dialog_util.dart';
|
import '../../utils/dialog_util.dart';
|
||||||
import '../../utils/log_util.dart';
|
import '../../utils/log_util.dart';
|
||||||
|
@ -152,6 +155,7 @@ class AuthenticationService {
|
||||||
await LicenseRepositoryImpl().cleanLicense();
|
await LicenseRepositoryImpl().cleanLicense();
|
||||||
DatabaseStorage.isInitialized = false;
|
DatabaseStorage.isInitialized = false;
|
||||||
await StorageHelper().init();
|
await StorageHelper().init();
|
||||||
|
|
||||||
context.go('/welcomePage', extra: extra);
|
context.go('/welcomePage', extra: extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue