wip
This commit is contained in:
parent
1d4041f92b
commit
742312e888
|
@ -1,779 +0,0 @@
|
|||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart';
|
||||
import 'package:hub/features/backend/index.dart';
|
||||
import 'package:hub/flutter_flow/flutter_flow_icon_button.dart';
|
||||
import 'package:hub/flutter_flow/flutter_flow_theme.dart';
|
||||
import 'package:hub/flutter_flow/flutter_flow_util.dart';
|
||||
import 'package:hub/shared/utils/dialog_util.dart';
|
||||
import 'package:hub/shared/utils/log_util.dart';
|
||||
import 'package:hub/shared/utils/snackbar_util.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
import '/flutter_flow/form_field_controller.dart';
|
||||
|
||||
import 'package:hub/flutter_flow/nav/nav.dart';
|
||||
import 'package:hub/shared/utils/limited_text_size.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:hub/features/storage/index.dart';
|
||||
|
||||
/// [ProvisionalHistoryEvent]
|
||||
class ProvisionalHistoryEvent {}
|
||||
|
||||
/// [LoadProvisionalHistory]
|
||||
class LoadProvisionalHistory extends ProvisionalHistoryEvent {}
|
||||
|
||||
/// [ProvisionalHistoryStateBloc]
|
||||
class ProvisionalHistoryStateBloc {
|
||||
final String devUUID;
|
||||
final String userUUID;
|
||||
final String cliUUID;
|
||||
final bool isLoading;
|
||||
|
||||
ProvisionalHistoryStateBloc({
|
||||
required this.devUUID,
|
||||
required this.userUUID,
|
||||
required this.cliUUID,
|
||||
this.isLoading = false,
|
||||
});
|
||||
|
||||
ProvisionalHistoryStateBloc copyWith({
|
||||
String? devUUID,
|
||||
String? userUUID,
|
||||
String? cliUUID,
|
||||
bool? isLoading,
|
||||
}) {
|
||||
return ProvisionalHistoryStateBloc(
|
||||
devUUID: devUUID ?? this.devUUID,
|
||||
userUUID: userUUID ?? this.userUUID,
|
||||
cliUUID: cliUUID ?? this.cliUUID,
|
||||
isLoading: isLoading ?? this.isLoading,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// [ProvisionalHistoryBloc]
|
||||
class ProvisionalHistoryBloc
|
||||
extends Bloc<ProvisionalHistoryEvent, ProvisionalHistoryStateBloc> {
|
||||
ProvisionalHistoryBloc()
|
||||
: super(ProvisionalHistoryStateBloc(
|
||||
devUUID: '', userUUID: '', cliUUID: '')) {
|
||||
on<LoadProvisionalHistory>(_onLoadProvisionalHistory);
|
||||
}
|
||||
|
||||
Future<void> _onLoadProvisionalHistory(
|
||||
LoadProvisionalHistory event,
|
||||
Emitter<ProvisionalHistoryStateBloc> emit,
|
||||
) async {
|
||||
emit(state.copyWith(isLoading: true));
|
||||
final devUUID =
|
||||
(await StorageHelper().get(ProfileStorageKey.devUUID.key)) ?? '';
|
||||
final userUUID =
|
||||
(await StorageHelper().get(ProfileStorageKey.userUUID.key)) ?? '';
|
||||
final cliUUID =
|
||||
(await StorageHelper().get(ProfileStorageKey.clientUUID.key)) ?? '';
|
||||
emit(state.copyWith(
|
||||
devUUID: devUUID,
|
||||
userUUID: userUUID,
|
||||
cliUUID: cliUUID,
|
||||
isLoading: false));
|
||||
}
|
||||
}
|
||||
|
||||
/// [ProvisionalHistoryPage]
|
||||
@immutable
|
||||
// ignore: must_be_immutable
|
||||
class ProvisionalHistoryPage extends StatefulWidget {
|
||||
Map<String, String> opt;
|
||||
|
||||
ProvisionalHistoryPage({super.key, Map<String, String>? opt})
|
||||
: opt = opt ?? const {'AGP_STATUS': '.*'};
|
||||
|
||||
@override
|
||||
State<ProvisionalHistoryPage> createState() => ProvisionalHistoryState(opt);
|
||||
}
|
||||
|
||||
/// [ProvisionalHistoryState]
|
||||
class ProvisionalHistoryState extends State<ProvisionalHistoryPage> {
|
||||
final BehaviorSubject<Map<String, String>> selectedTypeSubject;
|
||||
late ScrollController _scrollController;
|
||||
final scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
|
||||
bool _isSubjectClosed = false;
|
||||
int _pageNumber = 1;
|
||||
bool hasData = false;
|
||||
bool _loading = false;
|
||||
|
||||
String status = '.*';
|
||||
|
||||
late Future<void> future;
|
||||
List<dynamic> wrap = [];
|
||||
|
||||
ProvisionalHistoryState(Map<String, String> opt)
|
||||
: selectedTypeSubject = BehaviorSubject.seeded(opt) {
|
||||
selectedTypeSubject.listen((value) {});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
future = fetchHistoryService();
|
||||
_scrollController = ScrollController()
|
||||
..addListener(() {
|
||||
if (_scrollController.position.atEdge &&
|
||||
_scrollController.position.pixels != 0) {
|
||||
_loadMore();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
selectedTypeSubject.close();
|
||||
_isSubjectClosed = true;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = FlutterFlowTheme.of(context);
|
||||
return Scaffold(
|
||||
key: scaffoldKey,
|
||||
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
|
||||
appBar: _appBar(context, theme),
|
||||
body: _body(context),
|
||||
);
|
||||
}
|
||||
|
||||
PreferredSizeWidget _appBar(BuildContext context, FlutterFlowTheme theme) {
|
||||
return AppBar(
|
||||
backgroundColor: theme.primaryBackground,
|
||||
automaticallyImplyLeading: false,
|
||||
leading: _backButton(context, theme),
|
||||
title: _title(context, theme),
|
||||
centerTitle: true,
|
||||
elevation: 0.0,
|
||||
actions: [_filterButton(context)],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _backButton(BuildContext context, FlutterFlowTheme theme) {
|
||||
return FlutterFlowIconButton(
|
||||
key: ValueKey<String>('BackNavigationAppBar'),
|
||||
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 _title(BuildContext context, FlutterFlowTheme theme) {
|
||||
return Text(
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
ptText: 'Consultar Agendas',
|
||||
enText: 'Provisional History',
|
||||
),
|
||||
style: FlutterFlowTheme.of(context).headlineMedium.override(
|
||||
fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily,
|
||||
color: FlutterFlowTheme.of(context).primaryText,
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 0.0,
|
||||
useGoogleFonts: GoogleFonts.asMap()
|
||||
.containsKey(FlutterFlowTheme.of(context).headlineMediumFamily),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _filterButton(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: (context) {
|
||||
return GestureDetector(
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: GestureDetector(
|
||||
onTap: () {},
|
||||
child: FilterWidget(
|
||||
defaultSelections: selectedTypeSubject.value,
|
||||
filterOptions: {
|
||||
'AGP_STATUS': [
|
||||
{
|
||||
'title': FFLocalizations.of(context)
|
||||
.getVariableText(
|
||||
ptText: 'Ativo',
|
||||
enText: 'Active',
|
||||
),
|
||||
'value': 'AT',
|
||||
},
|
||||
{
|
||||
'title': FFLocalizations.of(context)
|
||||
.getVariableText(
|
||||
ptText: 'Concluído',
|
||||
enText: 'Completed',
|
||||
),
|
||||
'value': 'CO',
|
||||
},
|
||||
{
|
||||
'title': FFLocalizations.of(context)
|
||||
.getVariableText(
|
||||
ptText: 'Inativo',
|
||||
enText: 'Inactive',
|
||||
),
|
||||
'value': 'IN',
|
||||
},
|
||||
{
|
||||
'title': FFLocalizations.of(context)
|
||||
.getVariableText(
|
||||
ptText: 'Aguardando Aprovação',
|
||||
enText: 'Awaiting Approval',
|
||||
),
|
||||
'value': 'AA',
|
||||
},
|
||||
],
|
||||
},
|
||||
filterTitles: {'AGP_STATUS': ''},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
if (selectedFilter != null) {
|
||||
_updateHistoryAction(selectedFilter);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _updateHistoryAction(Map<String, String> newType) {
|
||||
if (!_isSubjectClosed) {
|
||||
final currentType = selectedTypeSubject.value;
|
||||
final updatedType = Map<String, String>.from(currentType);
|
||||
bool needsUpdate = false;
|
||||
newType.forEach((key, newValue) {
|
||||
if (currentType[key] != newValue) {
|
||||
updatedType[key] = newValue;
|
||||
needsUpdate = true;
|
||||
}
|
||||
});
|
||||
if (needsUpdate) {
|
||||
selectedTypeSubject.add(updatedType);
|
||||
fetchCardListViewService(updatedType);
|
||||
safeSetState(() {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<ApiCallResponse?> fetchHistoryService() async {
|
||||
try {
|
||||
setState(() => _loading = true);
|
||||
var response =
|
||||
await PhpGroup.getProvSchedules(_pageNumber.toString(), status);
|
||||
|
||||
final List<dynamic> history =
|
||||
response.jsonBody['agendamento']['value'] ?? [];
|
||||
|
||||
if (history.isNotEmpty) {
|
||||
setState(() {
|
||||
wrap.addAll(history);
|
||||
hasData = true;
|
||||
_loading = false;
|
||||
});
|
||||
return response;
|
||||
}
|
||||
SnackBarUtil.showNoMoreDataSnackbar(context);
|
||||
setState(() {
|
||||
hasData = false;
|
||||
_loading = false;
|
||||
});
|
||||
return null;
|
||||
} catch (e, s) {
|
||||
await DialogUtil.errorDefault(context);
|
||||
LogUtil.requestAPIFailed('processRequest', "", "Busca Acesso", e, s);
|
||||
setState(() {
|
||||
hasData = false;
|
||||
_loading = false;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Widget _body(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
if (hasData == false && _pageNumber <= 1 && _loading == false)
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Center(
|
||||
child: Text(
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
ptText: "Nenhum histórico encontrado!",
|
||||
enText: "No history found!"),
|
||||
)),
|
||||
],
|
||||
),
|
||||
)
|
||||
else if (hasData || _pageNumber >= 1)
|
||||
Expanded(child: _cardListViewOrganismWidget()),
|
||||
if (hasData == true && _loading)
|
||||
Container(
|
||||
padding: const EdgeInsets.only(top: 15, bottom: 15),
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
FlutterFlowTheme.of(context).primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _loadMore() {
|
||||
if (hasData == true) {
|
||||
_pageNumber++;
|
||||
future = fetchHistoryService();
|
||||
}
|
||||
}
|
||||
|
||||
void fetchCardListViewService(Map<String, String> select) {
|
||||
status = select['AGP_STATUS']!;
|
||||
wrap = [];
|
||||
_pageNumber = 1;
|
||||
future = fetchHistoryService();
|
||||
}
|
||||
|
||||
Widget _cardListViewOrganismWidget() {
|
||||
return FutureBuilder<void>(
|
||||
future: future,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting &&
|
||||
wrap.isEmpty) {
|
||||
return Center(
|
||||
child: SizedBox(
|
||||
width: 50.0,
|
||||
height: 50.0,
|
||||
child: SpinKitCircle(
|
||||
color: FlutterFlowTheme.of(context).primary,
|
||||
size: 50.0,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else if (snapshot.hasError) {
|
||||
return Center(
|
||||
child: Text(FFLocalizations.of(context).getVariableText(
|
||||
ptText: "Falha ao efetuar operação!",
|
||||
enText: "Failed to perform operation!")),
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
controller: _scrollController,
|
||||
itemCount: wrap.length,
|
||||
itemBuilder: (context, index) {
|
||||
final historyItem = wrap[index];
|
||||
return _historyCardMoleculeWidget(context, historyItem);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _historyCardMoleculeWidget(BuildContext context, dynamic historyItem) {
|
||||
return CardItemTemplateComponentWidget(
|
||||
imagePath: null,
|
||||
labelsHashMap: _buildLabelsHashMap(context, historyItem),
|
||||
statusHashMap: _buildStatusHashMap(context, historyItem),
|
||||
onTapCardItemAction: () async {},
|
||||
);
|
||||
}
|
||||
|
||||
String _imageUrlAtomWidget(String document, String type) {
|
||||
return valueOrDefault<String>(
|
||||
"https://freaccess.com.br/freaccess/getImage.php?&cliID=&atividade=getFoto&Documento=$document&tipo=$type",
|
||||
"https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/flutter-freaccess-hub-0xgz9q/assets/7ftdetkzc3s0/360_F_64676383_LdbmhiNM6Ypzb3FM4PPuFP9rHe7ri8Ju.jpg",
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, String> _buildLabelsHashMap(
|
||||
BuildContext context, dynamic historyItem) {
|
||||
return {
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
ptText: 'Nome:',
|
||||
enText: 'Name:',
|
||||
): historyItem['AGP_NOME'] ?? '',
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
ptText: 'Vencimento',
|
||||
enText: 'Expiration',
|
||||
): formatDate(historyItem['AGP_DT_VISITA']),
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
ptText: 'Observação:',
|
||||
enText: 'Observation:',
|
||||
): formatObs(historyItem['AGP_OBSERVACAO']),
|
||||
};
|
||||
}
|
||||
|
||||
String formatObs(String? obs) {
|
||||
if (obs == null || obs.isEmpty) {
|
||||
return FFLocalizations.of(context).getVariableText(
|
||||
ptText: 'Não fornecida',
|
||||
enText: 'No provided',
|
||||
);
|
||||
}
|
||||
return obs;
|
||||
}
|
||||
|
||||
String formatDate(String dateString) {
|
||||
DateTime dateTime = DateTime.parse(dateString);
|
||||
return "${dateTime.day.toString().padLeft(2, '0')}/${dateTime.month.toString().padLeft(2, '0')}/${dateTime.year} ${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}";
|
||||
}
|
||||
|
||||
List<Map<String, Color>> _buildStatusHashMap(
|
||||
BuildContext context, dynamic historyItem) {
|
||||
return [
|
||||
{
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
ptText: 'Visitante',
|
||||
enText: 'Visitor',
|
||||
): FlutterFlowTheme.of(context).alternate2,
|
||||
},
|
||||
_getStatusMap(context, historyItem)
|
||||
];
|
||||
}
|
||||
|
||||
Map<String, Color> _getStatusMap(BuildContext context, dynamic json) {
|
||||
late Map<String, Color> statusColorMap;
|
||||
log(DateTime.parse(json['AGP_DT_VISITA']).toString());
|
||||
log(DateTime.now().toString());
|
||||
final DateTime now = DateTime.now();
|
||||
final DateTime date = DateTime.parse(json['AGP_DT_VISITA']);
|
||||
final bool isExpired = now.isAfter(date);
|
||||
|
||||
final String statusMap = json['AGP_STATUS'];
|
||||
switch (statusMap) {
|
||||
case 'AT':
|
||||
return isExpired
|
||||
? {
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
ptText: 'Vencido',
|
||||
enText: 'Expired',
|
||||
): FlutterFlowTheme.of(context).error,
|
||||
}
|
||||
: {
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
ptText: 'Ativo',
|
||||
enText: 'Active',
|
||||
): FlutterFlowTheme.of(context).success,
|
||||
};
|
||||
case 'CO':
|
||||
return {
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
ptText: 'Concluido',
|
||||
enText: 'Completed',
|
||||
): Colors.blue,
|
||||
};
|
||||
case 'IN':
|
||||
return {
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
ptText: 'Inativo',
|
||||
enText: 'Inactive',
|
||||
): FlutterFlowTheme.of(context).error,
|
||||
};
|
||||
case 'AA':
|
||||
return {
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
ptText: 'Aguardando Aprovação',
|
||||
enText: 'Awaiting Approval',
|
||||
): FlutterFlowTheme.of(context).warning,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
FFLocalizations.of(context).getVariableText(
|
||||
ptText: 'Desconhecido',
|
||||
enText: 'Unknown',
|
||||
): FlutterFlowTheme.of(context).alternate2,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// [FilterModel]
|
||||
class FilterModel extends FlutterFlowModel<FilterWidget> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/// [FilterWidget]
|
||||
class FilterWidget extends StatefulWidget {
|
||||
final Map<String, dynamic> defaultSelections;
|
||||
final Map<String, List<Map<String, String>>> filterOptions;
|
||||
final Map<String, String> filterTitles;
|
||||
|
||||
const FilterWidget({
|
||||
super.key,
|
||||
required this.defaultSelections,
|
||||
required this.filterOptions,
|
||||
required this.filterTitles,
|
||||
});
|
||||
|
||||
@override
|
||||
_FilterWidgetState createState() => _FilterWidgetState();
|
||||
}
|
||||
|
||||
/// [_FilterWidgetState]
|
||||
class _FilterWidgetState extends State<FilterWidget> {
|
||||
late FilterModel _model;
|
||||
late Map<String, dynamic> selected;
|
||||
|
||||
@override
|
||||
void setState(VoidCallback callback) {
|
||||
super.setState(callback);
|
||||
_model.onUpdate();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_model = createModel(context, () => FilterModel());
|
||||
|
||||
_model.textController ??= TextEditingController();
|
||||
_model.textFieldFocusNode ??= FocusNode();
|
||||
|
||||
selected = Map<String, dynamic>.from(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]!;
|
||||
});
|
||||
setState(() {
|
||||
// Update the state with the new filter result
|
||||
selected = filterResult;
|
||||
});
|
||||
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] = option['value'];
|
||||
}
|
||||
} else {
|
||||
selected[key] = '';
|
||||
}
|
||||
});
|
||||
},
|
||||
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: screenWidth,
|
||||
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).getVariableText(
|
||||
ptText: 'Filtros',
|
||||
enText: 'Filters',
|
||||
),
|
||||
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).getVariableText(
|
||||
ptText: 'Aplicar',
|
||||
enText: 'Apply',
|
||||
),
|
||||
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),
|
||||
)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue