WIP
This commit is contained in:
parent
cb352b42ff
commit
13f07a237c
|
@ -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: (item, opt) => context.read<ProvisionalCubit>().filterLogic(item, opt),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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';
|
Loading…
Reference in New Issue