Merge pull request 'fix_change' (#61) from fix_change into main
Reviewed-on: https://repo.ravanertebat.com/TM/tm_app/pulls/61
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tm_app/core/routes/app_shell/desktop_shell_page.dart';
|
import 'package:tm_app/core/routes/app_shell/desktop_shell_page.dart';
|
||||||
import 'package:tm_app/core/routes/app_shell/mobile_shell_page.dart';
|
import 'package:tm_app/core/routes/app_shell/mobile_shell_page.dart';
|
||||||
import 'package:tm_app/core/routes/app_shell/tablet_shell_page.dart';
|
import 'package:tm_app/core/routes/app_shell/tablet_shell_page.dart';
|
||||||
|
import 'package:tm_app/view_models/home_view_model.dart';
|
||||||
import 'package:tm_app/views/shared/responsive_builder.dart';
|
import 'package:tm_app/views/shared/responsive_builder.dart';
|
||||||
|
|
||||||
class AppShellScreen extends StatelessWidget {
|
class AppShellScreen extends StatelessWidget {
|
||||||
@@ -10,11 +12,12 @@ class AppShellScreen extends StatelessWidget {
|
|||||||
|
|
||||||
final StatefulNavigationShell navigationShell;
|
final StatefulNavigationShell navigationShell;
|
||||||
|
|
||||||
void _gotoBranch(int index) {
|
void _gotoBranch(int index, BuildContext context) {
|
||||||
navigationShell.goBranch(
|
navigationShell.goBranch(
|
||||||
index,
|
index,
|
||||||
initialLocation: index == navigationShell.currentIndex,
|
initialLocation: index == navigationShell.currentIndex,
|
||||||
);
|
);
|
||||||
|
context.read<HomeViewModel>().init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -22,15 +25,15 @@ class AppShellScreen extends StatelessWidget {
|
|||||||
return ResponsiveBuilder(
|
return ResponsiveBuilder(
|
||||||
mobile: MobileShellPage(
|
mobile: MobileShellPage(
|
||||||
navigationShell: navigationShell,
|
navigationShell: navigationShell,
|
||||||
onTap: _gotoBranch,
|
onTap: (value) => _gotoBranch(value, context),
|
||||||
),
|
),
|
||||||
tablet: TabletShellPage(
|
tablet: TabletShellPage(
|
||||||
navigationShell: navigationShell,
|
navigationShell: navigationShell,
|
||||||
onTap: _gotoBranch,
|
onTap: (value) => _gotoBranch(value, context),
|
||||||
),
|
),
|
||||||
desktop: DesktopShellPage(
|
desktop: DesktopShellPage(
|
||||||
navigationShell: navigationShell,
|
navigationShell: navigationShell,
|
||||||
onTap: _gotoBranch,
|
onTap: (value) => _gotoBranch(value, context),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:tm_app/core/utils/result.dart';
|
import 'package:tm_app/core/utils/result.dart';
|
||||||
import 'package:tm_app/data/services/model/home/home_request/home_request_model.dart';
|
import 'package:tm_app/data/services/model/home/home_request/home_request_model.dart';
|
||||||
import 'package:tm_app/data/services/model/recommended_tenders_response/recommended_tenders_response.dart';
|
import 'package:tm_app/data/services/model/recommended_tenders_response/recommended_tenders_response.dart';
|
||||||
import 'package:tm_app/data/services/model/tender_approvals_state_response/tender_approvals_state_response.dart';
|
|
||||||
import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart';
|
import 'package:tm_app/data/services/model/tender_approvals_response/tender_approvals_response.dart';
|
||||||
|
import 'package:tm_app/data/services/model/tender_approvals_state_response/tender_approvals_state_response.dart';
|
||||||
import 'package:tm_app/data/services/model/tender_data/tender_data.dart';
|
import 'package:tm_app/data/services/model/tender_data/tender_data.dart';
|
||||||
|
|
||||||
import '../data/repositories/home_repository.dart';
|
import '../data/repositories/home_repository.dart';
|
||||||
@@ -14,9 +14,7 @@ class HomeViewModel with ChangeNotifier {
|
|||||||
|
|
||||||
HomeViewModel({required HomeRepository homeRepository})
|
HomeViewModel({required HomeRepository homeRepository})
|
||||||
: _homeRepository = homeRepository {
|
: _homeRepository = homeRepository {
|
||||||
getHome(homeRequestModel: HomeRequestModel(id: '1'));
|
init();
|
||||||
getYourTenders();
|
|
||||||
getApprovedStates();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
@@ -40,6 +38,11 @@ class HomeViewModel with ChangeNotifier {
|
|||||||
bool get isLoadingMore => _isLoadingMore;
|
bool get isLoadingMore => _isLoadingMore;
|
||||||
bool get hasMore => _hasMore;
|
bool get hasMore => _hasMore;
|
||||||
|
|
||||||
|
void init() async {
|
||||||
|
await getApprovedStates();
|
||||||
|
await getYourTenders();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> getHome({HomeRequestModel? homeRequestModel}) async {
|
Future<void> getHome({HomeRequestModel? homeRequestModel}) async {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
_errorMessage = null;
|
_errorMessage = null;
|
||||||
@@ -120,9 +123,7 @@ class HomeViewModel with ChangeNotifier {
|
|||||||
} else {
|
} else {
|
||||||
_tenders.clear();
|
_tenders.clear();
|
||||||
_tenders.addAll(
|
_tenders.addAll(
|
||||||
data!.data!
|
data!.data!.map((e) => e.tender).whereType<TenderData>(),
|
||||||
.map((e) => e.tender)
|
|
||||||
.whereType<TenderData>(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +136,8 @@ class HomeViewModel with ChangeNotifier {
|
|||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
Future<void> getApprovedStates() async {
|
|
||||||
|
Future<void> getApprovedStates() async {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
_errorMessage = null;
|
_errorMessage = null;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import 'package:tm_app/data/repositories/tenders_repository.dart';
|
|||||||
import 'package:tm_app/data/services/model/tender_data/tender_data.dart';
|
import 'package:tm_app/data/services/model/tender_data/tender_data.dart';
|
||||||
import 'package:tm_app/data/services/model/tender_detail_response/tender_detail_response_model.dart';
|
import 'package:tm_app/data/services/model/tender_detail_response/tender_detail_response_model.dart';
|
||||||
|
|
||||||
|
import '../data/services/model/tender_approvals_by_id_response/tender_approvals_by_id_response.dart';
|
||||||
|
import '../data/services/model/tender_approvals_data/tender_approvals_data.dart';
|
||||||
import '../data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart';
|
import '../data/services/model/tender_approvals_toggle_response/tender_approvals_toggle_response.dart';
|
||||||
|
|
||||||
class TenderDetailViewModel with ChangeNotifier {
|
class TenderDetailViewModel with ChangeNotifier {
|
||||||
@@ -22,14 +24,17 @@ class TenderDetailViewModel with ChangeNotifier {
|
|||||||
bool _isRejectApprovalLoading = false;
|
bool _isRejectApprovalLoading = false;
|
||||||
String? _errorMessage;
|
String? _errorMessage;
|
||||||
TenderData? _tenderDetail;
|
TenderData? _tenderDetail;
|
||||||
|
TenderApprovalsData? _tenderApprovalData;
|
||||||
bool approvalStatus = false;
|
bool approvalStatus = false;
|
||||||
|
String _status = '';
|
||||||
|
|
||||||
bool get isLoading => _isLoading;
|
bool get isLoading => _isLoading;
|
||||||
bool get isSubmitApprovalLoading => _isSubmitApprovalLoading;
|
bool get isSubmitApprovalLoading => _isSubmitApprovalLoading;
|
||||||
bool get isRejectApprovalLoading => _isRejectApprovalLoading;
|
bool get isRejectApprovalLoading => _isRejectApprovalLoading;
|
||||||
String? get errorMessage => _errorMessage;
|
String? get errorMessage => _errorMessage;
|
||||||
TenderData? get tenderDetail => _tenderDetail;
|
TenderData? get tenderDetail => _tenderDetail;
|
||||||
|
TenderApprovalsData? get tenderApprovalData => _tenderApprovalData;
|
||||||
|
String get status => _status;
|
||||||
|
|
||||||
Future<void> getTenderDetail({required String id}) async {
|
Future<void> getTenderDetail({required String id}) async {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
@@ -40,6 +45,7 @@ class TenderDetailViewModel with ChangeNotifier {
|
|||||||
switch (result) {
|
switch (result) {
|
||||||
case Ok<TenderDetailResponseModel>():
|
case Ok<TenderDetailResponseModel>():
|
||||||
_tenderDetail = result.value.data;
|
_tenderDetail = result.value.data;
|
||||||
|
await getTenderApprovals(id);
|
||||||
break;
|
break;
|
||||||
case Error<TenderDetailResponseModel>():
|
case Error<TenderDetailResponseModel>():
|
||||||
_errorMessage = result.error.toString();
|
_errorMessage = result.error.toString();
|
||||||
@@ -64,6 +70,7 @@ class TenderDetailViewModel with ChangeNotifier {
|
|||||||
switch (result) {
|
switch (result) {
|
||||||
case Ok<TenderApprovalsToggleResponse>():
|
case Ok<TenderApprovalsToggleResponse>():
|
||||||
approvalStatus = true;
|
approvalStatus = true;
|
||||||
|
_status = result.value.data?.status ?? '';
|
||||||
break;
|
break;
|
||||||
case Error<TenderApprovalsToggleResponse>():
|
case Error<TenderApprovalsToggleResponse>():
|
||||||
_errorMessage = result.error.toString();
|
_errorMessage = result.error.toString();
|
||||||
@@ -73,6 +80,7 @@ class TenderDetailViewModel with ChangeNotifier {
|
|||||||
_isSubmitApprovalLoading = false;
|
_isSubmitApprovalLoading = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
_errorMessage = null;
|
_errorMessage = null;
|
||||||
|
approvalStatus = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,6 +98,7 @@ class TenderDetailViewModel with ChangeNotifier {
|
|||||||
switch (result) {
|
switch (result) {
|
||||||
case Ok<TenderApprovalsToggleResponse>():
|
case Ok<TenderApprovalsToggleResponse>():
|
||||||
approvalStatus = true;
|
approvalStatus = true;
|
||||||
|
_status = result.value.data?.status ?? '';
|
||||||
break;
|
break;
|
||||||
case Error<TenderApprovalsToggleResponse>():
|
case Error<TenderApprovalsToggleResponse>():
|
||||||
_errorMessage = result.error.toString();
|
_errorMessage = result.error.toString();
|
||||||
@@ -99,6 +108,28 @@ class TenderDetailViewModel with ChangeNotifier {
|
|||||||
_isRejectApprovalLoading = false;
|
_isRejectApprovalLoading = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
_errorMessage = null;
|
_errorMessage = null;
|
||||||
|
approvalStatus = false;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getTenderApprovals(String tenderId) async {
|
||||||
|
_errorMessage = null;
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
|
final result = await _tendersRepository.getTenderApprovals(
|
||||||
|
tenderId: tenderId,
|
||||||
|
);
|
||||||
|
switch (result) {
|
||||||
|
case Ok<TenderApprovalsByIdResponse>():
|
||||||
|
_tenderApprovalData = result.value.data;
|
||||||
|
_status = result.value.data?.status ?? '';
|
||||||
|
break;
|
||||||
|
case Error<TenderApprovalsByIdResponse>():
|
||||||
|
_errorMessage = result.error.toString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
notifyListeners();
|
||||||
|
_errorMessage = null;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,6 +231,9 @@ class TendersViewModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Error<TenderApprovalsByIdResponse>():
|
case Error<TenderApprovalsByIdResponse>():
|
||||||
|
// Remove the tender from tenderApprovals if an error occurs for this tenderId
|
||||||
|
|
||||||
|
tenderApprovals.removeWhere((a) => a.tenderId == tenderId);
|
||||||
_errorMessage = result.error.toString();
|
_errorMessage = result.error.toString();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,60 @@ import 'package:tm_app/views/detail/widgets/tender_detail_card.dart';
|
|||||||
import 'package:tm_app/views/detail/widgets/tender_detail_header.dart';
|
import 'package:tm_app/views/detail/widgets/tender_detail_header.dart';
|
||||||
import 'package:tm_app/views/shared/tender_app_bar.dart';
|
import 'package:tm_app/views/shared/tender_app_bar.dart';
|
||||||
|
|
||||||
class TenderDetailMobilePage extends StatelessWidget {
|
class TenderDetailMobilePage extends StatefulWidget {
|
||||||
final String tenderId;
|
final String tenderId;
|
||||||
const TenderDetailMobilePage({required this.tenderId, super.key});
|
const TenderDetailMobilePage({required this.tenderId, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<TenderDetailMobilePage> createState() => _TenderDetailMobilePageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TenderDetailMobilePageState extends State<TenderDetailMobilePage> {
|
||||||
|
late final TenderDetailViewModel viewModel;
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
viewModel = context.read<TenderDetailViewModel>();
|
||||||
|
viewModel.addListener(_viewModelListener);
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _viewModelListener() {
|
||||||
|
if (viewModel.status.isNotEmpty &&
|
||||||
|
viewModel.status == 'approved' &&
|
||||||
|
viewModel.approvalStatus == true) {
|
||||||
|
ScaffoldMessenger.of(
|
||||||
|
context,
|
||||||
|
).showSnackBar(SnackBar(content: Text('tender approved successfully!')));
|
||||||
|
}
|
||||||
|
if (viewModel.status.isNotEmpty &&
|
||||||
|
viewModel.status == 'unapproved' &&
|
||||||
|
viewModel.approvalStatus == true) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(content: Text('tender approve removed sucessfully!')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (viewModel.status.isNotEmpty &&
|
||||||
|
viewModel.status == 'rejected' &&
|
||||||
|
viewModel.approvalStatus == true) {
|
||||||
|
ScaffoldMessenger.of(
|
||||||
|
context,
|
||||||
|
).showSnackBar(SnackBar(content: Text('tender rejected sucessfully!')));
|
||||||
|
}
|
||||||
|
if (viewModel.status.isNotEmpty &&
|
||||||
|
viewModel.status == 'unrejected' &&
|
||||||
|
viewModel.approvalStatus == true) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(content: Text('tender reject removed sucessfully!')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
viewModel.removeListener(_viewModelListener);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
|||||||
@@ -63,20 +63,27 @@ class TenderDetailActions extends StatelessWidget {
|
|||||||
backgroundColor: AppColors.primary30,
|
backgroundColor: AppColors.primary30,
|
||||||
textColor: AppColors.mainBlue,
|
textColor: AppColors.mainBlue,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showModalBottomSheet(
|
if (viewModel.status == 'approved') {
|
||||||
isDismissible: true,
|
viewModel.submitTenderApproval(
|
||||||
context: context,
|
tenderId: detail.id!,
|
||||||
builder: (context) {
|
submissionMode: 'self-apply',
|
||||||
return SelectSubmissionBottomSheet(
|
);
|
||||||
onConfirm: (value) {
|
} else {
|
||||||
viewModel.submitTenderApproval(
|
showModalBottomSheet(
|
||||||
tenderId: detail.id!,
|
isDismissible: true,
|
||||||
submissionMode: value,
|
context: context,
|
||||||
);
|
builder: (context) {
|
||||||
},
|
return SelectSubmissionBottomSheet(
|
||||||
);
|
onConfirm: (value) {
|
||||||
},
|
viewModel.submitTenderApproval(
|
||||||
);
|
tenderId: detail.id!,
|
||||||
|
submissionMode: value,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,9 +13,20 @@ import 'package:tm_app/views/shared/tender_app_bar.dart';
|
|||||||
|
|
||||||
import '../widgets.dart';
|
import '../widgets.dart';
|
||||||
|
|
||||||
class MobileHomePage extends StatelessWidget {
|
class MobileHomePage extends StatefulWidget {
|
||||||
const MobileHomePage({super.key});
|
const MobileHomePage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MobileHomePage> createState() => _MobileHomePageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MobileHomePageState extends State<MobileHomePage> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
// context.read<HomeViewModel>().init();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -32,8 +43,8 @@ class MobileHomePage extends StatelessWidget {
|
|||||||
return Center(child: Text(homeViewModel.errorMessage!));
|
return Center(child: Text(homeViewModel.errorMessage!));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (homeViewModel.homeResponse != null &&
|
if (homeViewModel.tenderApprovalsStateResponse != null &&
|
||||||
homeViewModel.tenderApprovalsStateResponse != null) {
|
homeViewModel.data != null) {
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class _ProgressBarColumnState extends State<ProgressBarColumn>
|
|||||||
Widget _centerText() {
|
Widget _centerText() {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'${widget.amount}%',
|
'${double.parse(widget.amount).round()}%',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 24.0.sp(),
|
fontSize: 24.0.sp(),
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:country_flags/country_flags.dart';
|
import 'package:country_flags/country_flags.dart';
|
||||||
import 'package:flutter/material.dart' hide DateUtils;
|
import 'package:flutter/material.dart' hide DateUtils;
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tm_app/core/constants/strings.dart';
|
import 'package:tm_app/core/constants/strings.dart';
|
||||||
import 'package:tm_app/core/routes/app_routes.dart';
|
import 'package:tm_app/core/routes/app_routes.dart';
|
||||||
import 'package:tm_app/data/services/model/tender_data/tender_data.dart';
|
import 'package:tm_app/data/services/model/tender_data/tender_data.dart';
|
||||||
@@ -9,6 +10,7 @@ import '../../../core/constants/assets.dart';
|
|||||||
import '../../../core/theme/colors.dart';
|
import '../../../core/theme/colors.dart';
|
||||||
import '../../../core/utils/date_utils.dart';
|
import '../../../core/utils/date_utils.dart';
|
||||||
import '../../../core/utils/size_config.dart';
|
import '../../../core/utils/size_config.dart';
|
||||||
|
import '../../../view_models/tenders_view_model.dart';
|
||||||
import 'tender_action_buttons_row.dart';
|
import 'tender_action_buttons_row.dart';
|
||||||
|
|
||||||
class TenderCard extends StatelessWidget {
|
class TenderCard extends StatelessWidget {
|
||||||
@@ -319,7 +321,13 @@ class TenderCard extends StatelessWidget {
|
|||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (tender.id != null) {
|
if (tender.id != null) {
|
||||||
TenderDetailRouteData(tenderId: tender.id!).push(context);
|
TenderDetailRouteData(tenderId: tender.id!).push(context).then((
|
||||||
|
value,
|
||||||
|
) {
|
||||||
|
if (context.mounted) {
|
||||||
|
context.read<TendersViewModel>().getTenderApprovals(tender.id!);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
|
|||||||
Reference in New Issue
Block a user