diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 7c56964..391a902 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -20,7 +20,5 @@
????
CFBundleVersion
1.0
- MinimumOSVersion
- 12.0
diff --git a/ios/Podfile b/ios/Podfile
index e549ee2..620e46e 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '12.0'
+# platform :ios, '13.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index d08bbb7..e13d49d 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -14,6 +14,7 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
+ 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -55,6 +56,7 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -62,6 +64,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -79,6 +82,7 @@
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
+ 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
@@ -142,6 +146,9 @@
productType = "com.apple.product-type.bundle.unit-test";
};
97C146ED1CF9000F007C117D /* Runner */ = {
+ packageProductDependencies = (
+ 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
+ );
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
@@ -165,6 +172,9 @@
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
+ packageReferences = (
+ 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */,
+ );
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
@@ -346,7 +356,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -472,7 +482,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -523,7 +533,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -611,6 +621,18 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
+/* Begin XCLocalSwiftPackageReference section */
+ 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = {
+ isa = XCLocalSwiftPackageReference;
+ relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
+ };
+/* End XCLocalSwiftPackageReference section */
+/* Begin XCSwiftPackageProductDependency section */
+ 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = FlutterGeneratedPluginSwiftPackage;
+ };
+/* End XCSwiftPackageProductDependency section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
new file mode 100644
index 0000000..7e63959
--- /dev/null
+++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -0,0 +1,176 @@
+{
+ "pins" : [
+ {
+ "identity" : "abseil-cpp-binary",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/google/abseil-cpp-binary.git",
+ "state" : {
+ "revision" : "bbe8b69694d7873315fd3a4ad41efe043e1c07c5",
+ "version" : "1.2024072200.0"
+ }
+ },
+ {
+ "identity" : "app-check",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/google/app-check.git",
+ "state" : {
+ "revision" : "61b85103a1aeed8218f17c794687781505fbbef5",
+ "version" : "11.2.0"
+ }
+ },
+ {
+ "identity" : "dkcamera",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/zhangao0086/DKCamera",
+ "state" : {
+ "branch" : "master",
+ "revision" : "5c691d11014b910aff69f960475d70e65d9dcc96"
+ }
+ },
+ {
+ "identity" : "dkimagepickercontroller",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/zhangao0086/DKImagePickerController",
+ "state" : {
+ "branch" : "4.3.9",
+ "revision" : "0bdfeacefa308545adde07bef86e349186335915"
+ }
+ },
+ {
+ "identity" : "dkphotogallery",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/zhangao0086/DKPhotoGallery",
+ "state" : {
+ "branch" : "master",
+ "revision" : "311c1bc7a94f1538f82773a79c84374b12a2ef3d"
+ }
+ },
+ {
+ "identity" : "firebase-ios-sdk",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/firebase/firebase-ios-sdk",
+ "state" : {
+ "revision" : "8d5b4189f1f482df8d5c58c9985ea70491ef5382",
+ "version" : "12.14.0"
+ }
+ },
+ {
+ "identity" : "google-ads-on-device-conversion-ios-sdk",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/googleads/google-ads-on-device-conversion-ios-sdk",
+ "state" : {
+ "revision" : "9bfcc6cf435b2e7c5562c1900b8680c594fa9a64",
+ "version" : "3.6.0"
+ }
+ },
+ {
+ "identity" : "googleappmeasurement",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/google/GoogleAppMeasurement.git",
+ "state" : {
+ "revision" : "219e564a8510e983e675c94f77f7f7c50049f22d",
+ "version" : "12.14.0"
+ }
+ },
+ {
+ "identity" : "googledatatransport",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/google/GoogleDataTransport.git",
+ "state" : {
+ "revision" : "617af071af9aa1d6a091d59a202910ac482128f9",
+ "version" : "10.1.0"
+ }
+ },
+ {
+ "identity" : "googleutilities",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/google/GoogleUtilities.git",
+ "state" : {
+ "revision" : "60da361632d0de02786f709bdc0c4df340f7613e",
+ "version" : "8.1.0"
+ }
+ },
+ {
+ "identity" : "grpc-binary",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/google/grpc-binary.git",
+ "state" : {
+ "revision" : "75b31c842f664a0f46a2e590a570e370249fd8f6",
+ "version" : "1.69.1"
+ }
+ },
+ {
+ "identity" : "gtm-session-fetcher",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/google/gtm-session-fetcher.git",
+ "state" : {
+ "revision" : "c0ac7575d70050c2973ba2318bd5af47f8e8153a",
+ "version" : "5.3.0"
+ }
+ },
+ {
+ "identity" : "interop-ios-for-google-sdks",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/google/interop-ios-for-google-sdks.git",
+ "state" : {
+ "revision" : "040d087ac2267d2ddd4cca36c757d1c6a05fdbfe",
+ "version" : "101.0.0"
+ }
+ },
+ {
+ "identity" : "leveldb",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/firebase/leveldb.git",
+ "state" : {
+ "revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1",
+ "version" : "1.22.5"
+ }
+ },
+ {
+ "identity" : "nanopb",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/firebase/nanopb.git",
+ "state" : {
+ "revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1",
+ "version" : "2.30910.0"
+ }
+ },
+ {
+ "identity" : "promises",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/google/promises.git",
+ "state" : {
+ "revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac",
+ "version" : "2.4.0"
+ }
+ },
+ {
+ "identity" : "sdwebimage",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/SDWebImage/SDWebImage",
+ "state" : {
+ "revision" : "2de3a496eaf6df9a1312862adcfd54acd73c39c0",
+ "version" : "5.21.7"
+ }
+ },
+ {
+ "identity" : "swiftygif",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/kirualex/SwiftyGif.git",
+ "state" : {
+ "revision" : "4430cbc148baa3907651d40562d96325426f409a",
+ "version" : "5.4.5"
+ }
+ },
+ {
+ "identity" : "tocropviewcontroller",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/TimOliver/TOCropViewController",
+ "state" : {
+ "revision" : "d4a6d8100f4b886fdbc8ae399bf144ff3e9afb7e",
+ "version" : "2.8.0"
+ }
+ }
+ ],
+ "version" : 2
+}
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 15cada4..c3fedb2 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -5,6 +5,24 @@
+
+
+
+
+
+
+
+
+
+
Bool {
- GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
+
+ func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
+ GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
+ }
}
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 3abf06c..a328b97 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -2,6 +2,8 @@
+ CADisableMinimumFrameDurationOnPhone
+
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
@@ -24,6 +26,29 @@
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+
+ UISceneConfigurations
+
+ UIWindowSceneSessionRoleApplication
+
+
+ UISceneClassName
+ UIWindowScene
+ UISceneConfigurationName
+ flutter
+ UISceneDelegateClassName
+ FlutterSceneDelegate
+ UISceneStoryboardFile
+ Main
+
+
+
+
+ UIApplicationSupportsIndirectInputEvents
+
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
@@ -41,9 +66,5 @@
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
- CADisableMinimumFrameDurationOnPhone
-
- UIApplicationSupportsIndirectInputEvents
-
diff --git a/lib/core/routes/app_routes.dart b/lib/core/routes/app_routes.dart
index f8aa9e6..4b039fe 100644
--- a/lib/core/routes/app_routes.dart
+++ b/lib/core/routes/app_routes.dart
@@ -250,11 +250,14 @@ class FinalCompletionOfDocumentsRouteData extends GoRouteData
@TypedGoRoute(path: '/completion_of_documents')
class CompletionOfDocumentsRouteData extends GoRouteData
with _$CompletionOfDocumentsRouteData {
- const CompletionOfDocumentsRouteData();
+ final String? tenderId;
+ const CompletionOfDocumentsRouteData({this.tenderId});
@override
Widget build(BuildContext context, GoRouterState state) {
- return const CompletionOfDocumentsScreen();
+ return tenderDetailProvider(
+ child: CompletionOfDocumentsScreen(tenderId: tenderId),
+ );
}
}
diff --git a/lib/core/routes/app_routes.g.dart b/lib/core/routes/app_routes.g.dart
index 261a276..d4e96d6 100644
--- a/lib/core/routes/app_routes.g.dart
+++ b/lib/core/routes/app_routes.g.dart
@@ -308,10 +308,20 @@ RouteBase get $completionOfDocumentsRouteData => GoRouteData.$route(
mixin _$CompletionOfDocumentsRouteData on GoRouteData {
static CompletionOfDocumentsRouteData _fromState(GoRouterState state) =>
- const CompletionOfDocumentsRouteData();
+ CompletionOfDocumentsRouteData(
+ tenderId: state.uri.queryParameters['tender-id'],
+ );
+
+ CompletionOfDocumentsRouteData get _self =>
+ this as CompletionOfDocumentsRouteData;
@override
- String get location => GoRouteData.$location('/completion_of_documents');
+ String get location => GoRouteData.$location(
+ '/completion_of_documents',
+ queryParams: {
+ if (_self.tenderId != null) 'tender-id': _self.tenderId!,
+ },
+ );
@override
void go(BuildContext context) => context.go(location);
diff --git a/lib/view_models/tender_detail_view_model.dart b/lib/view_models/tender_detail_view_model.dart
index d5b0b0d..a4c5f99 100644
--- a/lib/view_models/tender_detail_view_model.dart
+++ b/lib/view_models/tender_detail_view_model.dart
@@ -6,6 +6,7 @@ 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 '../core/constants/tender_approval_status.dart';
+import '../core/constants/tender_submision_mode.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';
@@ -143,4 +144,33 @@ class TenderDetailViewModel with ChangeNotifier {
_errorMessage = null;
notifyListeners();
}
+
+ /// Submits the tender for completion via the self-apply flow.
+ /// POSTs to /api/v1/tender-approvals with status "submitted" and
+ /// submission_mode "self-apply". Returns true on success.
+ Future submitForCompletion({required String tenderId}) async {
+ _isSubmitApprovalLoading = true;
+ _errorMessage = null;
+ notifyListeners();
+
+ bool success = false;
+ final result = await _tendersRepository.toggleApprovals(
+ tenderId: tenderId,
+ status: TenderApprovalStatus.submitted.value,
+ submissionMode: TenderSubmissionMode.selfApply.value,
+ );
+ switch (result) {
+ case Ok():
+ success = true;
+ _status = result.value.data?.status ?? '';
+ break;
+ case Error():
+ _errorMessage = result.error.toString();
+ break;
+ }
+
+ _isSubmitApprovalLoading = false;
+ notifyListeners();
+ return success;
+ }
}
diff --git a/lib/view_models/your_tenders_view_model.dart b/lib/view_models/your_tenders_view_model.dart
index a7aee20..493b373 100644
--- a/lib/view_models/your_tenders_view_model.dart
+++ b/lib/view_models/your_tenders_view_model.dart
@@ -206,7 +206,9 @@ class YourTendersViewModel with ChangeNotifier {
offset: _tendersOffset,
);
await getTenders(requestModel: requestModel);
- } else if (selectedStatus == YourTendersStrings.tendersSubmitted) {
+ } else if (selectedStatus == YourTendersStrings.tendersSubmitted ||
+ selectedStatus == TenderApprovalStatus.submitted.value ||
+ selectedStatus == TenderApprovalStatus.approved.value) {
final requestModel = GetTendersRequestModel(
status: TenderApprovalStatus.submitted.value,
createdFrom: startDateUnix,
@@ -299,10 +301,17 @@ class YourTendersViewModel with ChangeNotifier {
reset: true,
);
} else if (selectedStatus == TenderApprovalStatus.approved.value) {
- await getTendersFeedback(
- feedbackType: TenderApprovalStatus.approved.value,
- reset: true,
+ // "Approved tenders" maps to submitted tender-approvals. The API has no
+ // `approved` value; approved tenders are the ones a company has submitted
+ // for pursuit (GET /api/v1/tender-approvals?status=submitted).
+ final requestModel = GetTendersRequestModel(
+ status: TenderApprovalStatus.submitted.value,
+ createdFrom: startDateUnix,
+ createdTo: endDateUnix,
+ limit: _tendersLimit,
+ offset: _tendersOffset,
);
+ await getTenders(requestModel: requestModel, reset: true);
}
}
diff --git a/lib/views/completion_of_documents/pages/complectopn_of_documents_screen.dart b/lib/views/completion_of_documents/pages/complectopn_of_documents_screen.dart
index 2b902ee..b65d93e 100644
--- a/lib/views/completion_of_documents/pages/complectopn_of_documents_screen.dart
+++ b/lib/views/completion_of_documents/pages/complectopn_of_documents_screen.dart
@@ -7,7 +7,8 @@ import '../../../core/utils/size_config.dart';
import '../../shared/responsive_builder.dart';
class CompletionOfDocumentsScreen extends StatefulWidget {
- const CompletionOfDocumentsScreen({super.key});
+ final String? tenderId;
+ const CompletionOfDocumentsScreen({this.tenderId, super.key});
@override
State createState() => _CompletionOfDocumentsScreenState();
@@ -41,10 +42,10 @@ class _CompletionOfDocumentsScreenState extends State(
+ builder: (context, viewModel, _) => BaseButton(
+ isEnabled: !viewModel.isSubmitApprovalLoading,
+ isLoading: viewModel.isSubmitApprovalLoading,
+ onPressed: () => _submitForCompletion(context),
+ text:
+ CompletionOfDocumentsStrings
+ .submitForCompletion,
+ textColor: AppColors.textBlue,
+ backgroundColor: AppColors.primary30,
+ ),
),
SizedBox(height: 24.0.h()),
],
@@ -304,6 +312,26 @@ class CompletionOfDocumentsDesktopPage extends StatelessWidget {
);
}
+ Future _submitForCompletion(BuildContext context) async {
+ final id = tenderId;
+ if (id == null || id.isEmpty) {
+ AppToast.error(context, CompletionOfDocumentsStrings.submitError);
+ return;
+ }
+ final viewModel = context.read();
+ final success = await viewModel.submitForCompletion(tenderId: id);
+ if (!context.mounted) return;
+ if (success) {
+ AppToast.success(context, CompletionOfDocumentsStrings.submitSuccess);
+ context.pop();
+ } else {
+ AppToast.error(
+ context,
+ viewModel.errorMessage ?? CompletionOfDocumentsStrings.submitError,
+ );
+ }
+ }
+
Widget _docCard({
required String title,
required String subtitle,
diff --git a/lib/views/completion_of_documents/pages/m_completion_of_documents_page.dart b/lib/views/completion_of_documents/pages/m_completion_of_documents_page.dart
index 22bcbd2..0d28c32 100644
--- a/lib/views/completion_of_documents/pages/m_completion_of_documents_page.dart
+++ b/lib/views/completion_of_documents/pages/m_completion_of_documents_page.dart
@@ -3,13 +3,18 @@ import 'package:flutter_svg/svg.dart';
import 'package:tm_app/core/constants/assets.dart';
import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart';
+import 'package:go_router/go_router.dart';
+import 'package:provider/provider.dart';
+import 'package:tm_app/core/utils/app_toast.dart';
+import 'package:tm_app/view_models/tender_detail_view_model.dart';
import 'package:tm_app/views/completion_of_documents/strings/completion_of_documents_string.dart';
import 'package:tm_app/views/shared/base_button.dart';
import '../../shared/tender_app_bar.dart';
class CompletionOfDocumentsMobilePage extends StatelessWidget {
- const CompletionOfDocumentsMobilePage({super.key});
+ final String? tenderId;
+ const CompletionOfDocumentsMobilePage({this.tenderId, super.key});
@override
Widget build(BuildContext context) {
@@ -242,12 +247,15 @@ class CompletionOfDocumentsMobilePage extends StatelessWidget {
),
),
SizedBox(height: 24.0.h()),
- BaseButton(
- isEnabled: true,
- onPressed: () {},
- text: CompletionOfDocumentsStrings.submitForCompletion,
- textColor: AppColors.textBlue,
- backgroundColor: AppColors.primary30,
+ Consumer(
+ builder: (context, viewModel, _) => BaseButton(
+ isEnabled: !viewModel.isSubmitApprovalLoading,
+ isLoading: viewModel.isSubmitApprovalLoading,
+ onPressed: () => _submitForCompletion(context),
+ text: CompletionOfDocumentsStrings.submitForCompletion,
+ textColor: AppColors.textBlue,
+ backgroundColor: AppColors.primary30,
+ ),
),
],
),
@@ -256,6 +264,26 @@ class CompletionOfDocumentsMobilePage extends StatelessWidget {
);
}
+ Future _submitForCompletion(BuildContext context) async {
+ final id = tenderId;
+ if (id == null || id.isEmpty) {
+ AppToast.error(context, CompletionOfDocumentsStrings.submitError);
+ return;
+ }
+ final viewModel = context.read();
+ final success = await viewModel.submitForCompletion(tenderId: id);
+ if (!context.mounted) return;
+ if (success) {
+ AppToast.success(context, CompletionOfDocumentsStrings.submitSuccess);
+ context.pop();
+ } else {
+ AppToast.error(
+ context,
+ viewModel.errorMessage ?? CompletionOfDocumentsStrings.submitError,
+ );
+ }
+ }
+
Widget _docCard({
required String title,
required String subtitle,
diff --git a/lib/views/completion_of_documents/pages/t_completion_of_documents_page.dart b/lib/views/completion_of_documents/pages/t_completion_of_documents_page.dart
index adbeeff..de5a21b 100644
--- a/lib/views/completion_of_documents/pages/t_completion_of_documents_page.dart
+++ b/lib/views/completion_of_documents/pages/t_completion_of_documents_page.dart
@@ -3,6 +3,10 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:tm_app/core/constants/assets.dart';
import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart';
+import 'package:go_router/go_router.dart';
+import 'package:provider/provider.dart';
+import 'package:tm_app/core/utils/app_toast.dart';
+import 'package:tm_app/view_models/tender_detail_view_model.dart';
import 'package:tm_app/views/completion_of_documents/strings/completion_of_documents_string.dart';
import 'package:tm_app/views/shared/base_button.dart';
import 'package:tm_app/views/shared/tablet_desktop_appbar.dart';
@@ -10,7 +14,8 @@ import 'package:tm_app/views/shared/tablet_navigation_widget.dart';
import 'package:tm_app/views/shared/tender_app_bar.dart';
class CompletionOfDocumentsTabletPage extends StatelessWidget {
- const CompletionOfDocumentsTabletPage({super.key});
+ final String? tenderId;
+ const CompletionOfDocumentsTabletPage({this.tenderId, super.key});
@override
Widget build(BuildContext context) {
@@ -83,14 +88,17 @@ class CompletionOfDocumentsTabletPage extends StatelessWidget {
SizedBox(height: 24.0.h()),
- BaseButton(
- isEnabled: true,
- onPressed: () {},
- text:
- CompletionOfDocumentsStrings
- .submitForCompletion,
- textColor: AppColors.textBlue,
- backgroundColor: AppColors.primary30,
+ Consumer(
+ builder: (context, viewModel, _) => BaseButton(
+ isEnabled: !viewModel.isSubmitApprovalLoading,
+ isLoading: viewModel.isSubmitApprovalLoading,
+ onPressed: () => _submitForCompletion(context),
+ text:
+ CompletionOfDocumentsStrings
+ .submitForCompletion,
+ textColor: AppColors.textBlue,
+ backgroundColor: AppColors.primary30,
+ ),
),
],
),
@@ -309,6 +317,26 @@ class CompletionOfDocumentsTabletPage extends StatelessWidget {
);
}
+ Future _submitForCompletion(BuildContext context) async {
+ final id = tenderId;
+ if (id == null || id.isEmpty) {
+ AppToast.error(context, CompletionOfDocumentsStrings.submitError);
+ return;
+ }
+ final viewModel = context.read();
+ final success = await viewModel.submitForCompletion(tenderId: id);
+ if (!context.mounted) return;
+ if (success) {
+ AppToast.success(context, CompletionOfDocumentsStrings.submitSuccess);
+ context.pop();
+ } else {
+ AppToast.error(
+ context,
+ viewModel.errorMessage ?? CompletionOfDocumentsStrings.submitError,
+ );
+ }
+ }
+
// -------------------- Document Card --------------------
Widget _docCard({
required String title,
diff --git a/lib/views/completion_of_documents/strings/completion_of_documents_string.dart b/lib/views/completion_of_documents/strings/completion_of_documents_string.dart
index 14af095..c2baa04 100644
--- a/lib/views/completion_of_documents/strings/completion_of_documents_string.dart
+++ b/lib/views/completion_of_documents/strings/completion_of_documents_string.dart
@@ -7,4 +7,6 @@ class CompletionOfDocumentsStrings {
'Set Deadline for Completion of documents :';
static const String note = 'Note:';
static const String submitForCompletion = 'Submit for completion';
+ static const String submitSuccess = 'Tender submitted for completion';
+ static const String submitError = 'Failed to submit tender for completion';
}
diff --git a/lib/views/detail/widgets/tender_detail_action.dart b/lib/views/detail/widgets/tender_detail_action.dart
index e2a8e08..4dac05c 100644
--- a/lib/views/detail/widgets/tender_detail_action.dart
+++ b/lib/views/detail/widgets/tender_detail_action.dart
@@ -75,9 +75,9 @@ class _TenderDetailActionsState extends State {
// submissionMode: value,
// );
- const CompletionOfDocumentsRouteData().push(
- context,
- );
+ CompletionOfDocumentsRouteData(
+ tenderId: widget.detail.id!,
+ ).push(context);
} else if (value ==
TenderSubmissionMode.partnership.value) {
Future.delayed(Duration.zero, () {
@@ -213,8 +213,9 @@ class _TenderDetailActionsState extends State {
const FinalCompletionOfDocumentsRouteData()
.push(context);
} else {
- const CompletionOfDocumentsRouteData()
- .push(context);
+ CompletionOfDocumentsRouteData(
+ tenderId: widget.detail.id!,
+ ).push(context);
}
}
} else if (value ==
diff --git a/lib/views/profile/strings/profile_strings.dart b/lib/views/profile/strings/profile_strings.dart
index ab08801..f19f769 100644
--- a/lib/views/profile/strings/profile_strings.dart
+++ b/lib/views/profile/strings/profile_strings.dart
@@ -23,4 +23,5 @@ class ProfileStrings {
static const String mainDataTab = 'Main Data';
static const String membersTab = 'Members';
static const String subjectTab = 'Subject';
+ static const String appVersion = 'Version 1.0.7';
}
diff --git a/lib/views/profile/widgets/main_data_tab.dart b/lib/views/profile/widgets/main_data_tab.dart
index 9171a59..c176ada 100644
--- a/lib/views/profile/widgets/main_data_tab.dart
+++ b/lib/views/profile/widgets/main_data_tab.dart
@@ -98,6 +98,15 @@ class MainDataTab extends StatelessWidget {
),
),
),
+ SizedBox(height: 24.0.h()),
+ Text(
+ ProfileStrings.appVersion,
+ style: TextStyle(
+ fontSize: 12.0.sp(),
+ fontWeight: FontWeight.w400,
+ color: AppColors.grey70,
+ ),
+ ),
],
),
);