add infinite_scroll_View
This commit is contained in:
parent
05b3a612ba
commit
b0e4e86391
|
@ -529,7 +529,7 @@ void setAppLanguage(BuildContext context, String language) =>
|
||||||
void setDarkModeSetting(BuildContext context, ThemeMode themeMode) =>
|
void setDarkModeSetting(BuildContext context, ThemeMode themeMode) =>
|
||||||
App.of(context).setThemeMode(themeMode);
|
App.of(context).setThemeMode(themeMode);
|
||||||
|
|
||||||
void showSnackbar(
|
void showSnackbarMessenger(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
String message,
|
String message,
|
||||||
bool error, {
|
bool error, {
|
||||||
|
@ -573,6 +573,47 @@ void showSnackbar(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SnackBar showSnackbar(
|
||||||
|
BuildContext context,
|
||||||
|
String message,
|
||||||
|
bool error, {
|
||||||
|
bool loading = false,
|
||||||
|
int duration = 4,
|
||||||
|
}) {
|
||||||
|
return SnackBar(
|
||||||
|
content: Row(
|
||||||
|
children: [
|
||||||
|
if (loading)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.only(end: 10.0),
|
||||||
|
child: SizedBox(
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: FlutterFlowTheme.of(context).info,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
message,
|
||||||
|
style: TextStyle(
|
||||||
|
color: FlutterFlowTheme.of(context).info,
|
||||||
|
fontSize: LimitedFontSizeUtil.getBodyFontSize(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
duration: Duration(seconds: duration),
|
||||||
|
backgroundColor: error
|
||||||
|
? FlutterFlowTheme.of(context).error
|
||||||
|
: FlutterFlowTheme.of(context).success,
|
||||||
|
behavior: SnackBarBehavior.floating,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(30),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void showAlertDialog(BuildContext context, String title, String content,
|
void showAlertDialog(BuildContext context, String title, String content,
|
||||||
Future<void> Function() action) {
|
Future<void> Function() action) {
|
||||||
double limitedBodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context);
|
double limitedBodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context);
|
||||||
|
@ -785,5 +826,3 @@ double computeGradientAlignmentY(double evaluatedAngle) {
|
||||||
}
|
}
|
||||||
return double.parse(roundTo(y, 2));
|
return double.parse(roundTo(y, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -299,7 +299,7 @@ class _LiberationHistoryWidgetState extends State<LiberationHistoryWidget> {
|
||||||
)
|
)
|
||||||
.then((message) {
|
.then((message) {
|
||||||
if (message != null || message != '') {
|
if (message != null || message != '') {
|
||||||
showSnackbar(
|
showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
enText: 'Successfully resolved visit',
|
enText: 'Successfully resolved visit',
|
||||||
|
@ -308,7 +308,7 @@ class _LiberationHistoryWidgetState extends State<LiberationHistoryWidget> {
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
showSnackbar(context, message, true);
|
showSnackbarMessenger(context, message, true);
|
||||||
}
|
}
|
||||||
}).whenComplete(() {
|
}).whenComplete(() {
|
||||||
safeSetState(() {
|
safeSetState(() {
|
||||||
|
|
|
@ -474,7 +474,7 @@ class PetsPageModel extends FlutterFlowModel<PetsPageWidget> {
|
||||||
context.pop(value);
|
context.pop(value);
|
||||||
|
|
||||||
if (value == false) {
|
if (value == false) {
|
||||||
showSnackbar(
|
showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
ptText: 'Erro ao excluir pet',
|
ptText: 'Erro ao excluir pet',
|
||||||
|
@ -483,7 +483,7 @@ class PetsPageModel extends FlutterFlowModel<PetsPageWidget> {
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
} else if (value == true) {
|
} else if (value == true) {
|
||||||
showSnackbar(
|
showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
enText: 'Success deleting pet',
|
enText: 'Success deleting pet',
|
||||||
|
@ -494,7 +494,7 @@ class PetsPageModel extends FlutterFlowModel<PetsPageWidget> {
|
||||||
}
|
}
|
||||||
}).catchError((err, stack) {
|
}).catchError((err, stack) {
|
||||||
context.pop();
|
context.pop();
|
||||||
showSnackbar(
|
showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
enText: 'Error deleting pet',
|
enText: 'Error deleting pet',
|
||||||
|
|
|
@ -472,7 +472,7 @@ class ScheduleCompleteVisitPageModel
|
||||||
context.pop(value);
|
context.pop(value);
|
||||||
|
|
||||||
if (value == false) {
|
if (value == false) {
|
||||||
showSnackbar(
|
showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
enText: 'Error blocking visit',
|
enText: 'Error blocking visit',
|
||||||
|
@ -481,7 +481,7 @@ class ScheduleCompleteVisitPageModel
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
} else if (value == true) {
|
} else if (value == true) {
|
||||||
showSnackbar(
|
showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
enText: 'Success canceling visit',
|
enText: 'Success canceling visit',
|
||||||
|
@ -492,7 +492,7 @@ class ScheduleCompleteVisitPageModel
|
||||||
}
|
}
|
||||||
}).catchError((err, stack) {
|
}).catchError((err, stack) {
|
||||||
context.pop();
|
context.pop();
|
||||||
showSnackbar(
|
showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
enText: 'Error blocking visit',
|
enText: 'Error blocking visit',
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
part of 'vehicles_on_the_property.dart';
|
part of 'vehicles_on_the_property.dart';
|
||||||
|
|
||||||
/// [VehicleHistoryScreen] is a StatefulWidget that displays a list of vehicles.
|
/// Widget que exibe o histórico de veículos na propriedade.
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
|
||||||
class VehicleHistoryScreen extends StatefulWidget {
|
class VehicleHistoryScreen extends StatefulWidget {
|
||||||
|
final VehicleModel model;
|
||||||
|
|
||||||
VehicleHistoryScreen(this.model, {super.key});
|
VehicleHistoryScreen(this.model, {super.key});
|
||||||
late VehicleModel model;
|
|
||||||
final scaffoldKey = GlobalKey<ScaffoldState>();
|
|
||||||
final builderKey = GlobalKey();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<VehicleHistoryScreen> createState() => _VehicleHistoryScreenState();
|
State<VehicleHistoryScreen> createState() => _VehicleHistoryScreenState();
|
||||||
|
@ -15,167 +12,268 @@ class VehicleHistoryScreen extends StatefulWidget {
|
||||||
|
|
||||||
class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
||||||
with Remotable {
|
with Remotable {
|
||||||
@override
|
final apiCall = PhpGroup.getVehiclesByProperty;
|
||||||
void dispose() {
|
|
||||||
super.dispose();
|
|
||||||
_pagingController.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_initializeScrollController();
|
_pagingController.addPageRequestListener(
|
||||||
_pagingController.addPageRequestListener(_fetch);
|
(dynamic pageKey) => _fetch(
|
||||||
|
hasData: () async {
|
||||||
|
final newItems = await apiCall.call(pageKey.toString());
|
||||||
|
if (newItems.jsonBody == null) return (false, null);
|
||||||
|
final List<dynamic> vehicles =
|
||||||
|
(newItems.jsonBody['vehicles'] as List<dynamic>?) ?? [];
|
||||||
|
_pagingController.nextPageKey = pageKey + 1;
|
||||||
|
|
||||||
|
safeSetState(() {
|
||||||
|
count = newItems.jsonBody['total_rows'] ?? 0;
|
||||||
|
});
|
||||||
|
return (vehicles.isNotEmpty, vehicles);
|
||||||
|
},
|
||||||
|
onNotHas: () {
|
||||||
|
_showNoMoreDataSnackBar(context);
|
||||||
|
setState(() {
|
||||||
|
// _hasData = false;
|
||||||
|
// _loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onHas: (vehicles) {
|
||||||
|
setState(() {
|
||||||
|
// _loading = false;
|
||||||
|
});
|
||||||
|
_pagingController.appendLastPage(vehicles);
|
||||||
|
},
|
||||||
|
onError: (e, s) {
|
||||||
|
DialogUtil.errorDefault(context);
|
||||||
|
LogUtil.requestAPIFailed(
|
||||||
|
"proccessRequest.php", "", "Consulta de Veículo", e, s);
|
||||||
|
setState(() {
|
||||||
|
// _hasData = false;
|
||||||
|
// _loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
_pagingController.addStatusListener(_showError);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_pagingController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _showError(PagingStatus status) async {
|
||||||
|
if (status == PagingStatus.subsequentPageError) {
|
||||||
|
final message = FFLocalizations.of(context).getVariableText(
|
||||||
|
enText: 'Something went wrong while fetching a new page.',
|
||||||
|
ptText: 'Algo deu errado ao buscar uma nova página.',
|
||||||
|
);
|
||||||
|
final retry = FFLocalizations.of(context).getVariableText(
|
||||||
|
enText: 'Retry',
|
||||||
|
ptText: 'Recarregar',
|
||||||
|
);
|
||||||
|
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(message),
|
||||||
|
action: SnackBarAction(
|
||||||
|
label: retry,
|
||||||
|
onPressed: () => _pagingController.retryLastFailedRequest(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
late final limitedHeaderTextSize =
|
|
||||||
LimitedFontSizeUtil.getHeaderFontSize(context);
|
|
||||||
late final double limitedBodyTextSize =
|
|
||||||
LimitedFontSizeUtil.getBodyFontSize(context);
|
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
// if (_hasData == false &&
|
_buildHeader(context),
|
||||||
// _pageNumber <= 1 &&
|
_buildBody(),
|
||||||
// _loading == false)
|
],
|
||||||
// _buildNoDataFound(context, limitedHeaderTextSize)
|
|
||||||
// else if (_hasData == true || _pageNumber >= 1)
|
|
||||||
_buildHistoryList(context, limitedBodyTextSize),
|
|
||||||
// if (_hasData == true && _loading == true)
|
|
||||||
// _buildLoadingIndicator(context),
|
|
||||||
].addToStart(const SizedBox(height: 0)),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildNoDataFound(BuildContext context, double limitedHeaderTextSize) {
|
Widget _buildHeader(BuildContext context) {
|
||||||
return Expanded(
|
final bodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context);
|
||||||
child: Column(
|
return SizedBox(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
height: 30,
|
||||||
mainAxisSize: MainAxisSize.max,
|
child: Center(
|
||||||
children: [
|
child: Text(
|
||||||
Center(
|
(widget.model.amountRegister == '0' ||
|
||||||
child: Text(
|
widget.model.amountRegister == null)
|
||||||
FFLocalizations.of(context).getVariableText(
|
? ''
|
||||||
ptText: "Nenhum veículo encontrado!",
|
: "${FFLocalizations.of(context).getVariableText(ptText: "Quantidade de Veículos: ", enText: "Amount of Vehicles: ")}${widget.model.amountRegister}/$count",
|
||||||
enText: "No vehicle found",
|
textAlign: TextAlign.right,
|
||||||
),
|
style: TextStyle(
|
||||||
style: TextStyle(
|
fontFamily: 'Nunito',
|
||||||
fontFamily: 'Nunito',
|
fontSize: bodyFontSize,
|
||||||
fontSize: limitedHeaderTextSize,
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHistoryList(BuildContext context, double limitedBodyTextSize) {
|
Expanded _buildBody() {
|
||||||
|
final noDataFound = FFLocalizations.of(context).getVariableText(
|
||||||
|
ptText: "Nenhum veículo encontrado!",
|
||||||
|
enText: "No vehicle found",
|
||||||
|
);
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: RefreshIndicator(
|
child: RefreshIndicator(
|
||||||
onRefresh: () async => _pagingController.refresh(),
|
onRefresh: () async => _pagingController.refresh(),
|
||||||
child: PagedListView<int, dynamic>(
|
child: PagedListView<int, dynamic>(
|
||||||
// separatorBuilder: (context, index) => const Divider(),
|
|
||||||
pagingController: _pagingController,
|
pagingController: _pagingController,
|
||||||
builderDelegate: PagedChildBuilderDelegate(
|
builderDelegate: PagedChildBuilderDelegate<dynamic>(
|
||||||
animateTransitions: true,
|
animateTransitions: true,
|
||||||
itemBuilder: (context, item, index) =>
|
itemBuilder: (context, item, index) =>
|
||||||
_generateItems(context, index, item),
|
_generateItems(context, index, item),
|
||||||
firstPageErrorIndicatorBuilder: (context) => Placeholder(),
|
// noMoreItemsIndicatorBuilder: ,
|
||||||
newPageErrorIndicatorBuilder: (context) => Placeholder(),
|
newPageProgressIndicatorBuilder: (context) =>
|
||||||
|
_buildLoadingIndicator(context),
|
||||||
|
firstPageProgressIndicatorBuilder: (context) =>
|
||||||
|
_buildLoadingIndicator(context),
|
||||||
|
noItemsFoundIndicatorBuilder: (context) =>
|
||||||
|
_buildNoDataFound(context, noDataFound),
|
||||||
|
firstPageErrorIndicatorBuilder: (context) => const Placeholder(),
|
||||||
|
newPageErrorIndicatorBuilder: (context) => const Placeholder(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListView.builder(
|
Widget _generateItems(BuildContext context, int index, dynamic item) {
|
||||||
// shrinkWrap: true,
|
log('item: $item');
|
||||||
// addAutomaticKeepAlives: true,
|
final bool? isOwner = item['isOwnerVehicle'];
|
||||||
// restorationId: '',
|
final IconData iconData =
|
||||||
// physics: const BouncingScrollPhysics(),
|
isOwner == true ? Symbols.garage : Symbols.directions_car;
|
||||||
// controller: _scrollController,
|
|
||||||
// itemCount: _wrap.length,
|
|
||||||
// itemBuilder: (context, index) => _generateItems(context, _wrap[index], index),
|
|
||||||
|
|
||||||
// ),
|
final FreCardIcon? cardIcon = isOwner != null
|
||||||
|
? FreCardIcon(
|
||||||
|
height: 50,
|
||||||
|
width: 100,
|
||||||
|
icon: Icon(iconData, size: 80, opticalSize: 10),
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
|
||||||
Widget _buildLoadingIndicator(BuildContext context) {
|
final String? tag = item['tag'];
|
||||||
return Container(
|
final bool containTag = tag.isNotNullAndEmpty;
|
||||||
padding: const EdgeInsets.only(top: 15, bottom: 15),
|
final Map<String, String> labelsHashMap =
|
||||||
child: Center(
|
_generateLabelsHashMap(context, item, tag, containTag);
|
||||||
child: CircularProgressIndicator(
|
|
||||||
valueColor: AlwaysStoppedAnimation<Color>(
|
final List<Map<String, Color>> statusHashMapList =
|
||||||
FlutterFlowTheme.of(context).primary,
|
_generateStatusHashMapList(item);
|
||||||
),
|
|
||||||
),
|
Future<void> onTapCardItemAction() async {
|
||||||
),
|
await _handleCardItemTap(context, cardIcon, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
final statusLinkedHashMap = statusHashMapList
|
||||||
|
.map((map) => LinkedHashMap<String, Color>.from(map))
|
||||||
|
.toList();
|
||||||
|
final length = statusLinkedHashMap.expand((e) => [e.length]);
|
||||||
|
final double itemWidthFactor = length == 1 ? 0.25 : 0.50;
|
||||||
|
|
||||||
|
return CardItemTemplateComponentWidget(
|
||||||
|
icon: cardIcon,
|
||||||
|
labelsHashMap: labelsHashMap,
|
||||||
|
statusHashMap: statusHashMapList,
|
||||||
|
onTapCardItemAction: onTapCardItemAction,
|
||||||
|
itemWidthFactor: itemWidthFactor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<String, String> _generateLabelsHashMap(
|
||||||
|
BuildContext context,
|
||||||
|
Map<String, dynamic> item,
|
||||||
|
String? tag,
|
||||||
|
bool containTag,
|
||||||
|
) {
|
||||||
|
final localization = FFLocalizations.of(context);
|
||||||
|
return {
|
||||||
|
'${localization.getVariableText(ptText: "Placa", enText: "License Plate")}:':
|
||||||
|
item['licensePlate'] ?? '',
|
||||||
|
'${localization.getVariableText(ptText: "Modelo", enText: "Model")}:':
|
||||||
|
item['model'] ?? '',
|
||||||
|
'${localization.getVariableText(ptText: "Proprietário", enText: "Owner")}:':
|
||||||
|
item['personName'] ?? '',
|
||||||
|
if (containTag)
|
||||||
|
'${localization.getVariableText(ptText: "Tag", enText: "Tag")}:':
|
||||||
|
tag ?? '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, Color>> _generateStatusHashMapList(
|
||||||
|
Map<String, dynamic> item) {
|
||||||
|
final statusHashMap = widget.model.generateStatusColorMap(item, false);
|
||||||
|
return statusHashMap != null ? [statusHashMap] : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _handleCardItemTap(
|
||||||
|
BuildContext context,
|
||||||
|
FreCardIcon? cardIcon,
|
||||||
|
Map<String, dynamic> item,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
final dialogContent = widget.model.buildVehicleDetails(
|
||||||
|
icon: cardIcon,
|
||||||
|
item: item,
|
||||||
|
context: context,
|
||||||
|
model: widget.model,
|
||||||
|
);
|
||||||
|
|
||||||
|
await showDialog(
|
||||||
|
useSafeArea: true,
|
||||||
|
context: context,
|
||||||
|
builder: (context) => Dialog(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: dialogContent,
|
||||||
|
),
|
||||||
|
).whenComplete(() {
|
||||||
|
safeSetState(() {
|
||||||
|
// _pagingController.refresh();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (e, s) {
|
||||||
|
DialogUtil.errorDefault(context);
|
||||||
|
LogUtil.requestAPIFailed(
|
||||||
|
"proccessRequest.php", "", "Consulta de Veículos", e, s);
|
||||||
|
safeSetState(() {
|
||||||
|
// _hasData = false;
|
||||||
|
// _loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin Remotable on State<VehicleHistoryScreen> {
|
mixin Remotable on State<VehicleHistoryScreen> {
|
||||||
final PagingController<int, dynamic> _pagingController =
|
final PagingController<int, dynamic> _pagingController =
|
||||||
PagingController<int, dynamic>(firstPageKey: 1);
|
PagingController<int, dynamic>(firstPageKey: 1);
|
||||||
|
|
||||||
// late ScrollController _scrollController;
|
|
||||||
double offset = 0.0;
|
double offset = 0.0;
|
||||||
List<dynamic> _wrap = [];
|
// bool _hasData = true;
|
||||||
int _pageNumber = 1;
|
// bool _loading = true;
|
||||||
bool _hasData = true;
|
|
||||||
bool _loading = true;
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
Future<void> _fetch(dynamic pageKey) async {
|
Future<void> _fetch({
|
||||||
if (!_hasData || !_loading) return;
|
required Future<(bool, dynamic)> Function() hasData,
|
||||||
print('hasHasData');
|
required void Function(dynamic) onHas,
|
||||||
// setState(() => _loading = true);
|
required void Function() onNotHas,
|
||||||
|
required void Function(Object, StackTrace) onError,
|
||||||
|
}) async {
|
||||||
|
// if (!_hasData || !_loading) return;
|
||||||
try {
|
try {
|
||||||
var newItems =
|
final (bool, dynamic) data = await hasData();
|
||||||
await PhpGroup.getVehiclesByProperty.call(pageKey.toString());
|
if (data.$1)
|
||||||
final bool isLastPage = newItems.jsonBody == null ||
|
onHas(data.$2);
|
||||||
newItems.jsonBody == [] ||
|
else
|
||||||
newItems.jsonBody == '';
|
onNotHas();
|
||||||
|
|
||||||
if (newItems.jsonBody == null) {
|
|
||||||
} else {
|
|
||||||
final List<dynamic> vehicles =
|
|
||||||
newItems.jsonBody['vehicles'] as List<dynamic>? ?? [];
|
|
||||||
_pagingController.nextPageKey = pageKey + 1;
|
|
||||||
|
|
||||||
safeSetState(() => count = newItems.jsonBody['total_rows'] ?? 0);
|
|
||||||
if (vehicles.isNotEmpty) {
|
|
||||||
// setState(() {
|
|
||||||
// _hasData = true;
|
|
||||||
// _loading = false;
|
|
||||||
// _wrap.addAll(vehicles);
|
|
||||||
// });
|
|
||||||
_pagingController.appendLastPage(vehicles);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_showNoMoreDataSnackBar(context);
|
|
||||||
setState(() {
|
|
||||||
_hasData = false;
|
|
||||||
_loading = false;
|
|
||||||
});
|
|
||||||
print('hasEmpty: ${_wrap.length}');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
DialogUtil.errorDefault(context);
|
onError(e, s);
|
||||||
LogUtil.requestAPIFailed(
|
|
||||||
"proccessRequest.php", "", "Consulta de Veículo", e, s);
|
|
||||||
setState(() {
|
|
||||||
_hasData = false;
|
|
||||||
_loading = false;
|
|
||||||
});
|
|
||||||
print('hasError');
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,142 +286,32 @@ mixin Remotable on State<VehicleHistoryScreen> {
|
||||||
showSnackbar(context, message, true);
|
showSnackbar(context, message, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHeader(BuildContext context) {
|
Widget _buildNoDataFound(BuildContext context, String title) {
|
||||||
double limitedBodyTextSize = LimitedFontSizeUtil.getBodyFontSize(context);
|
final headerFontSize = LimitedFontSizeUtil.getHeaderFontSize(context);
|
||||||
log('amountRegister: ${widget.model.amountRegister}');
|
// final bodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context);
|
||||||
return Padding(
|
return Expanded(
|
||||||
padding: const EdgeInsets.only(right: 30, top: 10),
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
(widget.model.amountRegister == '0' ||
|
title,
|
||||||
widget.model.amountRegister == null)
|
style: TextStyle(
|
||||||
? ''
|
fontFamily: 'Nunito',
|
||||||
: "${FFLocalizations.of(context).getVariableText(ptText: "Quantidade de Veículos: ", enText: "Amount of Vehicles: ")}${widget.model.amountRegister}/$count",
|
fontSize: headerFontSize,
|
||||||
textAlign: TextAlign.right,
|
),
|
||||||
style: TextStyle(
|
|
||||||
fontFamily: 'Nunito',
|
|
||||||
fontSize: limitedBodyTextSize,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _generateItems(BuildContext context, int index, dynamic item) {
|
Widget _buildLoadingIndicator(BuildContext context) {
|
||||||
log('item: $item');
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 15),
|
||||||
// return Placeholder();
|
child: Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
// if (index == 0) return _buildHeader(context);
|
valueColor: AlwaysStoppedAnimation<Color>(
|
||||||
|
FlutterFlowTheme.of(context).primary,
|
||||||
final bool? isOwner = item['isOwnerVehicle'];
|
),
|
||||||
final IconData? iconData =
|
),
|
||||||
isOwner == true ? Symbols.garage : Symbols.directions_car;
|
),
|
||||||
final FreCardIcon? cardIcon = isOwner != null
|
|
||||||
? FreCardIcon(
|
|
||||||
height: 50,
|
|
||||||
width: 100,
|
|
||||||
icon: Icon(iconData, size: 80, opticalSize: 10))
|
|
||||||
: null;
|
|
||||||
|
|
||||||
final String? tag = item['tag'];
|
|
||||||
final bool containTag = tag.isNotNullAndEmpty;
|
|
||||||
final Map<String, String> labelsHashMap =
|
|
||||||
_generateLabelsHashMap(context, item, tag, containTag);
|
|
||||||
|
|
||||||
final List<Map<String, Color>> statusHashMapList =
|
|
||||||
_generateStatusHashMapList(item);
|
|
||||||
|
|
||||||
Future<void> onTapCardItemAction() async {
|
|
||||||
_handleCardItemTap(context, cardIcon, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
final statusLinkedHashMap = statusHashMapList
|
|
||||||
.map((map) => LinkedHashMap<String, Color>.from(map))
|
|
||||||
.toList();
|
|
||||||
final length = statusLinkedHashMap.expand((e) => [e.length]);
|
|
||||||
|
|
||||||
return CardItemTemplateComponentWidget(
|
|
||||||
icon: cardIcon,
|
|
||||||
labelsHashMap: labelsHashMap,
|
|
||||||
statusHashMap: statusHashMapList,
|
|
||||||
onTapCardItemAction: onTapCardItemAction,
|
|
||||||
itemWidthFactor: length == 1 ? 0.25 : 0.50,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> _generateLabelsHashMap(BuildContext context,
|
|
||||||
Map<String, dynamic> uItem, String? tag, bool containTag) {
|
|
||||||
return {
|
|
||||||
'${FFLocalizations.of(context).getVariableText(ptText: "Placa", enText: "License Plate")}:':
|
|
||||||
uItem['licensePlate'] ?? '',
|
|
||||||
'${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:':
|
|
||||||
uItem['model'] ?? '',
|
|
||||||
'${FFLocalizations.of(context).getVariableText(ptText: "Proprietário", enText: "Owner")}:':
|
|
||||||
uItem['personName'] ?? '',
|
|
||||||
if (containTag)
|
|
||||||
'${FFLocalizations.of(context).getVariableText(ptText: "Tag", enText: "Tag")}:':
|
|
||||||
tag ?? '',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Map<String, Color>> _generateStatusHashMapList(
|
|
||||||
Map<String, dynamic> uItem) {
|
|
||||||
final statusHashMap = widget.model.generateStatusColorMap(uItem, false);
|
|
||||||
return statusHashMap != null ? [statusHashMap] : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _handleCardItemTap(BuildContext context, FreCardIcon? cardIcon,
|
|
||||||
Map<String, dynamic> uItem) async {
|
|
||||||
try {
|
|
||||||
final dialogContent = widget.model.buildVehicleDetails(
|
|
||||||
icon: cardIcon,
|
|
||||||
item: uItem,
|
|
||||||
context: context,
|
|
||||||
model: widget.model,
|
|
||||||
);
|
|
||||||
|
|
||||||
await showDialog(
|
|
||||||
useSafeArea: true,
|
|
||||||
context: context,
|
|
||||||
builder: (context) =>
|
|
||||||
Dialog(alignment: Alignment.center, child: dialogContent),
|
|
||||||
).whenComplete(() {
|
|
||||||
safeSetState(() {
|
|
||||||
_pageNumber = 1;
|
|
||||||
_fetch(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} catch (e, s) {
|
|
||||||
DialogUtil.errorDefault(context);
|
|
||||||
LogUtil.requestAPIFailed(
|
|
||||||
"proccessRequest.php", "", "Consulta de Veículos", e, s);
|
|
||||||
safeSetState(() {
|
|
||||||
_hasData = false;
|
|
||||||
_loading = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _initializeScrollController() {
|
|
||||||
// _scrollController = ScrollController(keepScrollOffset: true, initialScrollOffset: offset)
|
|
||||||
// ..addListener(() {
|
|
||||||
// print('ScrollController');
|
|
||||||
// if(!_hasData) return;
|
|
||||||
// if
|
|
||||||
// // (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent)
|
|
||||||
// (_scrollController.position.atEdge && _scrollController.position.pixels != 0)
|
|
||||||
// {
|
|
||||||
// print('ScrollController -> loadMore');
|
|
||||||
// offset = _scrollController.offset;
|
|
||||||
// _loadMore();
|
|
||||||
// }
|
|
||||||
// },);
|
|
||||||
}
|
|
||||||
|
|
||||||
// void _loadMore() {
|
|
||||||
// if (_hasData) {
|
|
||||||
// _pageNumber+=1;
|
|
||||||
// _loading = true;
|
|
||||||
// _fetch(_pageNumber);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,8 @@ class VehicleModel extends FlutterFlowModel<VehiclePage>
|
||||||
Future<void> initAsync() async {
|
Future<void> initAsync() async {
|
||||||
amountRegister =
|
amountRegister =
|
||||||
await StorageHelper().get(LocalsStorageKey.vehicleAmountRegister.key);
|
await StorageHelper().get(LocalsStorageKey.vehicleAmountRegister.key);
|
||||||
autoApproval= await StorageHelper().get(LocalsStorageKey.vehicleAutoApproval.key);
|
autoApproval =
|
||||||
|
await StorageHelper().get(LocalsStorageKey.vehicleAutoApproval.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFormValid(BuildContext context, GlobalKey<FormState> formKey) {
|
bool isFormValid(BuildContext context, GlobalKey<FormState> formKey) {
|
||||||
|
@ -91,7 +92,6 @@ mixin class _BaseVehiclePage {
|
||||||
ApiCallResponse? vehicleResponse;
|
ApiCallResponse? vehicleResponse;
|
||||||
String? amountRegister = '0';
|
String? amountRegister = '0';
|
||||||
late final String? autoApproval;
|
late final String? autoApproval;
|
||||||
|
|
||||||
|
|
||||||
VoidCallback? onUpdateVehicle;
|
VoidCallback? onUpdateVehicle;
|
||||||
VoidCallback? onRegisterVehicle;
|
VoidCallback? onRegisterVehicle;
|
||||||
|
@ -240,10 +240,7 @@ mixin _VehicleUpdateScreenModel on _BaseVehiclePage {
|
||||||
|
|
||||||
/// [_VehicleHistoryScreenModel] is a mixin that contains the business logic of the vehicle history page.
|
/// [_VehicleHistoryScreenModel] is a mixin that contains the business logic of the vehicle history page.
|
||||||
mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
|
Map<String, Color>? generateStatusColorMap(dynamic uItem, bool isDetail) {
|
||||||
|
|
||||||
Map<String, Color>? generateStatusColorMap(dynamic uItem, bool isDetail) {
|
|
||||||
|
|
||||||
if (autoApproval.toBoolean == true) return null;
|
if (autoApproval.toBoolean == true) return null;
|
||||||
final theme = FlutterFlowTheme.of(context);
|
final theme = FlutterFlowTheme.of(context);
|
||||||
final localization = FFLocalizations.of(context);
|
final localization = FFLocalizations.of(context);
|
||||||
|
@ -299,7 +296,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
List<FFButtonWidget> generateActionButtons(dynamic item) {
|
List<FFButtonWidget> generateActionButtons(dynamic item) {
|
||||||
final Color iconButtonColor = FlutterFlowTheme.of(context).primaryText;
|
final Color iconButtonColor = FlutterFlowTheme.of(context).primaryText;
|
||||||
final FFButtonOptions buttonOptions = FFButtonOptions(
|
final FFButtonOptions buttonOptions = FFButtonOptions(
|
||||||
height: 40,
|
height: 40,
|
||||||
|
@ -342,7 +339,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
ptText: 'Você tem certeza que deseja cancelar essa solicitação?',
|
ptText: 'Você tem certeza que deseja cancelar essa solicitação?',
|
||||||
enText: 'Are you sure you want to delete this request?',
|
enText: 'Are you sure you want to delete this request?',
|
||||||
),
|
),
|
||||||
() async => processCancelRequest(item['status'], item));
|
() async => processCancelRequest(item['status'], item));
|
||||||
}
|
}
|
||||||
|
|
||||||
final deleteText = FFLocalizations.of(context)
|
final deleteText = FFLocalizations.of(context)
|
||||||
|
@ -359,7 +356,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
ptText: 'Você tem certeza que deseja excluir esse veículo?',
|
ptText: 'Você tem certeza que deseja excluir esse veículo?',
|
||||||
enText: 'Are you sure you want to delete this vehicle?',
|
enText: 'Are you sure you want to delete this vehicle?',
|
||||||
),
|
),
|
||||||
() async => processDeleteRequest(item),
|
() async => processDeleteRequest(item),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +417,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
// ignore: unrelated_type_equality_checks
|
// ignore: unrelated_type_equality_checks
|
||||||
if (value.jsonBody['error'] == true) {
|
if (value.jsonBody['error'] == true) {
|
||||||
final String errorMsg = value.jsonBody['error_msg'];
|
final String errorMsg = value.jsonBody['error_msg'];
|
||||||
return showSnackbar(
|
return showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
ptText: errorMsg,
|
ptText: errorMsg,
|
||||||
|
@ -430,7 +427,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
);
|
);
|
||||||
// ignore: unrelated_type_equality_checks
|
// ignore: unrelated_type_equality_checks
|
||||||
}
|
}
|
||||||
return showSnackbar(
|
return showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
enText: 'Success deleting vehicle',
|
enText: 'Success deleting vehicle',
|
||||||
|
@ -440,7 +437,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
);
|
);
|
||||||
}).catchError((err, stack) {
|
}).catchError((err, stack) {
|
||||||
context.pop();
|
context.pop();
|
||||||
return showSnackbar(
|
return showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
enText: 'Error deleting vehicle',
|
enText: 'Error deleting vehicle',
|
||||||
|
@ -473,7 +470,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
|
|
||||||
if (value.jsonBody['error'] == true) {
|
if (value.jsonBody['error'] == true) {
|
||||||
final String errorMsg = value.jsonBody['error_msg'];
|
final String errorMsg = value.jsonBody['error_msg'];
|
||||||
return showSnackbar(
|
return showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
ptText: errorMsg,
|
ptText: errorMsg,
|
||||||
|
@ -482,7 +479,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return showSnackbar(
|
return showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
enText: 'Success canceling request',
|
enText: 'Success canceling request',
|
||||||
|
@ -492,7 +489,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
context.pop();
|
context.pop();
|
||||||
return showSnackbar(
|
return showSnackbarMessenger(
|
||||||
context,
|
context,
|
||||||
FFLocalizations.of(context).getVariableText(
|
FFLocalizations.of(context).getVariableText(
|
||||||
enText: 'Error canceling request',
|
enText: 'Error canceling request',
|
||||||
|
@ -503,7 +500,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ApiCallResponse> processCancelDeleteRequest(dynamic item) async{
|
Future<ApiCallResponse> processCancelDeleteRequest(dynamic item) async {
|
||||||
return await PhpGroup.deleteVehicle.call(
|
return await PhpGroup.deleteVehicle.call(
|
||||||
vehicleId: item['vehicleId'],
|
vehicleId: item['vehicleId'],
|
||||||
licensePlate: item['licensePlate'],
|
licensePlate: item['licensePlate'],
|
||||||
|
@ -512,7 +509,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ApiCallResponse> processCancelUpdateRequest(dynamic item) async {
|
Future<ApiCallResponse> processCancelUpdateRequest(dynamic item) async {
|
||||||
return await PhpGroup.deleteVehicle.call(
|
return await PhpGroup.deleteVehicle.call(
|
||||||
vehicleId: item['vehicleId'],
|
vehicleId: item['vehicleId'],
|
||||||
licensePlate: item['licensePlate'],
|
licensePlate: item['licensePlate'],
|
||||||
|
@ -530,7 +527,7 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> generateLabelsHashMap(dynamic item) {
|
Map<String, String> generateLabelsHashMap(dynamic item) {
|
||||||
return {
|
return {
|
||||||
if (item['model'] != null && item['model'] != '')
|
if (item['model'] != null && item['model'] != '')
|
||||||
'${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:':
|
'${FFLocalizations.of(context).getVariableText(ptText: "Modelo", enText: "Model")}:':
|
||||||
|
@ -555,10 +552,10 @@ mixin _VehicleHistoryScreenModel on _BaseVehiclePage {
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required VehicleModel model,
|
required VehicleModel model,
|
||||||
required FreCardIcon? icon,
|
required FreCardIcon? icon,
|
||||||
}) {
|
}) {
|
||||||
final status = generateStatusColorMap(item, true);
|
final status = generateStatusColorMap(item, true);
|
||||||
final buttons = generateActionButtons(item);
|
final buttons = generateActionButtons(item);
|
||||||
final labels = generateLabelsHashMap(item);
|
final labels = generateLabelsHashMap(item);
|
||||||
return DetailsComponentWidget(
|
return DetailsComponentWidget(
|
||||||
icon: icon,
|
icon: icon,
|
||||||
buttons: buttons,
|
buttons: buttons,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:hub/components/atomic_components/shared_components_atoms/custom_input.dart';
|
import 'package:hub/components/atomic_components/shared_components_atoms/custom_input.dart';
|
||||||
|
|
Loading…
Reference in New Issue