Add Docker support and enhance data models for tender details

- Introduced a .dockerignore file to optimize Docker builds by excluding unnecessary files.
- Updated the Dockerfile to use a Flutter base image, enabling web builds for the application.
- Added new data models for `Lot` and `OrganizationAddress` to represent tender details more accurately.
- Enhanced the `Organization` model to include `companyId` and a nested `address` field.
- Updated the `TenderData` model to include new fields such as `noticeTypeCode`, `formType`, and `lots`, reflecting the API response structure.
- Regenerated necessary code for data models to ensure compatibility with the updated structures.
This commit is contained in:
AmirReza Jamali
2026-06-03 13:32:42 +03:30
parent 83b77c05ef
commit dde66521f6
35 changed files with 1362 additions and 659 deletions
@@ -25,8 +25,41 @@ class MainTendersSlider extends StatefulWidget {
class _MainTendersSliderState extends State<MainTendersSlider> {
final PageController pageController = PageController(initialPage: 0);
final ScrollController _scrollController = ScrollController();
int currentPage = 1;
/// Start prefetching the next page once this fraction of the currently
/// loaded items has been scrolled/swiped past.
static const double _prefetchFraction = 0.5;
@override
void initState() {
super.initState();
_scrollController.addListener(_onScroll);
}
void _onScroll() {
if (!_scrollController.hasClients) {
return;
}
final position = _scrollController.position;
if (position.maxScrollExtent <= 0) {
return;
}
if (position.pixels >= position.maxScrollExtent * _prefetchFraction) {
_maybeLoadMore();
}
}
void _maybeLoadMore() {
final viewModel = context.read<TendersViewModel>();
if (viewModel.hasMoreData &&
!viewModel.isLoadingMore &&
!viewModel.isLoading) {
viewModel.loadMoreTenders();
}
}
void _goToPreviousPage() {
if (currentPage == 1) {
return;
@@ -82,6 +115,7 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
@override
void dispose() {
pageController.dispose();
_scrollController.dispose();
super.dispose();
}
@@ -115,6 +149,12 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
if (!viewModel.hasFeedbackForTender(id)) {
viewModel.getTenderFeedback(id);
}
// Infinite scroll: once we pass the halfway point of the loaded
// tenders, prefetch the next page in the background.
if (index >= (widget.tenders.length * _prefetchFraction).floor()) {
_maybeLoadMore();
}
},
itemBuilder: (context, index) {
final tender = widget.tenders[index];
@@ -230,6 +270,7 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
children: [
Expanded(
child: ListView.separated(
controller: _scrollController,
padding: EdgeInsets.all(16.0.h()),
itemCount:
widget.tenders.length +