WIP
This commit is contained in:
parent
a89edb0ae4
commit
92a8986a7e
|
@ -1,3 +0,0 @@
|
||||||
export 'data_sources/index.dart';
|
|
||||||
export 'repositories/index.dart';
|
|
||||||
export 'models/index.dart';
|
|
|
@ -1,3 +0,0 @@
|
||||||
export 'entities/index.dart';
|
|
||||||
export 'respositories/index.dart';
|
|
||||||
export 'usecases/index.dart';
|
|
|
@ -1,3 +0,0 @@
|
||||||
export 'data/index.dart';
|
|
||||||
export 'domain/index.dart';
|
|
||||||
export 'presentation/index.dart';
|
|
|
@ -1,117 +0,0 @@
|
||||||
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 {}
|
|
|
@ -1,2 +0,0 @@
|
||||||
export 'history_bloc_template.dart';
|
|
||||||
export 'provisional_history_bloc.dart';
|
|
|
@ -1,3 +0,0 @@
|
||||||
export 'blocs/index.dart';
|
|
||||||
export 'pages/index.dart';
|
|
||||||
export 'widgets/index.dart';
|
|
|
@ -1,106 +0,0 @@
|
||||||
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};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,211 +0,0 @@
|
||||||
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);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
export 'history_page_template.dart';
|
|
||||||
export 'provisional_history_page.dart';
|
|
|
@ -1,105 +0,0 @@
|
||||||
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};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,229 +0,0 @@
|
||||||
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),
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export 'filter_modal.dart';
|
|
|
@ -4,7 +4,6 @@ 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';
|
||||||
|
@ -131,7 +130,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) => ProvisionalHistoryPage()),
|
FFRoute(name: 'messageHistoryPage', path: '/messageHistoryPage', builder: (context, params) => const MessageHistoryPageWidget()),
|
||||||
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()),
|
||||||
|
|
Loading…
Reference in New Issue