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:
@@ -0,0 +1,16 @@
|
||||
build
|
||||
.dart_tool
|
||||
.git
|
||||
.gitignore
|
||||
.drone.yml
|
||||
.vscode
|
||||
.idea
|
||||
.flutter-plugins-dependencies
|
||||
README.md
|
||||
*.md
|
||||
Dockerfile
|
||||
Dockerfile-old
|
||||
.dockerignore
|
||||
artifacts
|
||||
ios
|
||||
android
|
||||
+22
-2
@@ -1,3 +1,23 @@
|
||||
FROM docker-mirror.ravanertebat.ir/hub/nginx:1.25.2-alpine3.18-slim
|
||||
FROM docker-mirror.ravanertebat.ir/ghcr/cirruslabs/flutter:3.38.10 AS base
|
||||
|
||||
COPY ./artifacts/flutter/tm_pwa /usr/share/nginx/html
|
||||
WORKDIR /app
|
||||
RUN flutter config --enable-web
|
||||
|
||||
FROM base AS deps
|
||||
COPY pubspec.yaml pubspec.lock ./
|
||||
RUN flutter pub get
|
||||
|
||||
FROM base AS builder
|
||||
# Pull in the resolved package config from deps so `flutter pub get` is not
|
||||
# re-run when only source files change.
|
||||
COPY --from=deps /app/.dart_tool ./.dart_tool
|
||||
COPY . .
|
||||
RUN flutter build web --release --output=build/tm_pwa
|
||||
|
||||
FROM docker-mirror.ravanertebat.ir/hub/nginx:1.25.2-alpine3.18-slim AS runner
|
||||
|
||||
COPY --from=builder /app/build/tm_pwa /usr/share/nginx/html
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
|
||||
@@ -47,7 +47,6 @@ mixin _$LoginScreenRoute on GoRouteData {
|
||||
|
||||
RouteBase get $splashScreenRoute => GoRouteData.$route(
|
||||
path: '/splash',
|
||||
|
||||
factory: _$SplashScreenRoute._fromState,
|
||||
);
|
||||
|
||||
@@ -111,40 +110,33 @@ RouteBase get $appShellRouteData => StatefulShellRouteData.$route(
|
||||
branches: [
|
||||
StatefulShellBranchData.$branch(
|
||||
navigatorKey: HomeBranch.$navigatorKey,
|
||||
|
||||
routes: [
|
||||
GoRouteData.$route(path: '/home', factory: _$HomeRouteData._fromState),
|
||||
],
|
||||
),
|
||||
StatefulShellBranchData.$branch(
|
||||
navigatorKey: TendersBranch.$navigatorKey,
|
||||
|
||||
routes: [
|
||||
GoRouteData.$route(
|
||||
path: '/tenders',
|
||||
|
||||
factory: _$TendersRouteData._fromState,
|
||||
),
|
||||
],
|
||||
),
|
||||
StatefulShellBranchData.$branch(
|
||||
navigatorKey: NotificationBranch.$navigatorKey,
|
||||
|
||||
routes: [
|
||||
GoRouteData.$route(
|
||||
path: '/notification',
|
||||
|
||||
factory: _$NotificationRouteData._fromState,
|
||||
),
|
||||
],
|
||||
),
|
||||
StatefulShellBranchData.$branch(
|
||||
navigatorKey: ProfileBranch.$navigatorKey,
|
||||
|
||||
routes: [
|
||||
GoRouteData.$route(
|
||||
path: '/profile',
|
||||
|
||||
factory: _$ProfileRouteData._fromState,
|
||||
),
|
||||
],
|
||||
@@ -242,7 +234,6 @@ mixin _$ProfileRouteData on GoRouteData {
|
||||
|
||||
RouteBase get $yourTendersRouteData => GoRouteData.$route(
|
||||
path: '/your-tenders',
|
||||
|
||||
factory: _$YourTendersRouteData._fromState,
|
||||
);
|
||||
|
||||
@@ -274,7 +265,6 @@ mixin _$YourTendersRouteData on GoRouteData {
|
||||
|
||||
RouteBase get $finalCompletionOfDocumentsRouteData => GoRouteData.$route(
|
||||
path: '/final_completion_of_documents',
|
||||
|
||||
factory: _$FinalCompletionOfDocumentsRouteData._fromState,
|
||||
);
|
||||
|
||||
@@ -302,7 +292,6 @@ mixin _$FinalCompletionOfDocumentsRouteData on GoRouteData {
|
||||
|
||||
RouteBase get $completionOfDocumentsRouteData => GoRouteData.$route(
|
||||
path: '/completion_of_documents',
|
||||
|
||||
factory: _$CompletionOfDocumentsRouteData._fromState,
|
||||
);
|
||||
|
||||
@@ -318,9 +307,7 @@ mixin _$CompletionOfDocumentsRouteData on GoRouteData {
|
||||
@override
|
||||
String get location => GoRouteData.$location(
|
||||
'/completion_of_documents',
|
||||
queryParams: {
|
||||
if (_self.tenderId != null) 'tender-id': _self.tenderId!,
|
||||
},
|
||||
queryParams: {if (_self.tenderId != null) 'tender-id': _self.tenderId},
|
||||
);
|
||||
|
||||
@override
|
||||
@@ -339,7 +326,6 @@ mixin _$CompletionOfDocumentsRouteData on GoRouteData {
|
||||
|
||||
RouteBase get $likedTendersRouteData => GoRouteData.$route(
|
||||
path: '/like-tenders',
|
||||
|
||||
factory: _$LikedTendersRouteData._fromState,
|
||||
);
|
||||
|
||||
@@ -390,7 +376,6 @@ mixin _$BoardRouteData on GoRouteData {
|
||||
|
||||
RouteBase get $tenderDetailRouteData => GoRouteData.$route(
|
||||
path: '/tender-detail',
|
||||
|
||||
factory: _$TenderDetailRouteData._fromState,
|
||||
);
|
||||
|
||||
@@ -422,7 +407,6 @@ mixin _$TenderDetailRouteData on GoRouteData {
|
||||
|
||||
RouteBase get $forgotPasswordRouteData => GoRouteData.$route(
|
||||
path: '/forgot-password',
|
||||
|
||||
factory: _$ForgotPasswordRouteData._fromState,
|
||||
);
|
||||
|
||||
@@ -449,7 +433,6 @@ mixin _$ForgotPasswordRouteData on GoRouteData {
|
||||
|
||||
RouteBase get $forgotPasswordOtpRouteData => GoRouteData.$route(
|
||||
path: '/forgot-password-otp',
|
||||
|
||||
factory: _$ForgotPasswordOtpRouteData._fromState,
|
||||
);
|
||||
|
||||
@@ -481,7 +464,6 @@ mixin _$ForgotPasswordOtpRouteData on GoRouteData {
|
||||
|
||||
RouteBase get $forgotPasswordCreateRouteData => GoRouteData.$route(
|
||||
path: '/forgot-password-create',
|
||||
|
||||
factory: _$ForgotPasswordCreateRouteData._fromState,
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// ignore_for_file: invalid_annotation_target
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'lot.freezed.dart';
|
||||
part 'lot.g.dart';
|
||||
|
||||
// AI-NOTE (for PR reviewer): New model for entries in the tender-details
|
||||
// `lots` array. Only lot_id, title and description are mapped — the fields the
|
||||
// tender-details "Lots" section renders. Add more fields here if the UI grows.
|
||||
@freezed
|
||||
abstract class Lot with _$Lot {
|
||||
const factory Lot({
|
||||
@JsonKey(name: 'lot_id') required String? lotId,
|
||||
required String? title,
|
||||
required String? description,
|
||||
}) = _Lot;
|
||||
|
||||
factory Lot.fromJson(Map<String, Object?> json) => _$LotFromJson(json);
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'lot.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$Lot {
|
||||
|
||||
@JsonKey(name: 'lot_id') String? get lotId; String? get title; String? get description;
|
||||
/// Create a copy of Lot
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$LotCopyWith<Lot> get copyWith => _$LotCopyWithImpl<Lot>(this as Lot, _$identity);
|
||||
|
||||
/// Serializes this Lot to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is Lot&&(identical(other.lotId, lotId) || other.lotId == lotId)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,lotId,title,description);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Lot(lotId: $lotId, title: $title, description: $description)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $LotCopyWith<$Res> {
|
||||
factory $LotCopyWith(Lot value, $Res Function(Lot) _then) = _$LotCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
@JsonKey(name: 'lot_id') String? lotId, String? title, String? description
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$LotCopyWithImpl<$Res>
|
||||
implements $LotCopyWith<$Res> {
|
||||
_$LotCopyWithImpl(this._self, this._then);
|
||||
|
||||
final Lot _self;
|
||||
final $Res Function(Lot) _then;
|
||||
|
||||
/// Create a copy of Lot
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? lotId = freezed,Object? title = freezed,Object? description = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
lotId: freezed == lotId ? _self.lotId : lotId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [Lot].
|
||||
extension LotPatterns on Lot {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _Lot value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _Lot() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _Lot value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _Lot():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _Lot value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _Lot() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function(@JsonKey(name: 'lot_id') String? lotId, String? title, String? description)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _Lot() when $default != null:
|
||||
return $default(_that.lotId,_that.title,_that.description);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function(@JsonKey(name: 'lot_id') String? lotId, String? title, String? description) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _Lot():
|
||||
return $default(_that.lotId,_that.title,_that.description);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function(@JsonKey(name: 'lot_id') String? lotId, String? title, String? description)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _Lot() when $default != null:
|
||||
return $default(_that.lotId,_that.title,_that.description);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _Lot implements Lot {
|
||||
const _Lot({@JsonKey(name: 'lot_id') required this.lotId, required this.title, required this.description});
|
||||
factory _Lot.fromJson(Map<String, dynamic> json) => _$LotFromJson(json);
|
||||
|
||||
@override@JsonKey(name: 'lot_id') final String? lotId;
|
||||
@override final String? title;
|
||||
@override final String? description;
|
||||
|
||||
/// Create a copy of Lot
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$LotCopyWith<_Lot> get copyWith => __$LotCopyWithImpl<_Lot>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$LotToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Lot&&(identical(other.lotId, lotId) || other.lotId == lotId)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,lotId,title,description);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Lot(lotId: $lotId, title: $title, description: $description)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$LotCopyWith<$Res> implements $LotCopyWith<$Res> {
|
||||
factory _$LotCopyWith(_Lot value, $Res Function(_Lot) _then) = __$LotCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
@JsonKey(name: 'lot_id') String? lotId, String? title, String? description
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$LotCopyWithImpl<$Res>
|
||||
implements _$LotCopyWith<$Res> {
|
||||
__$LotCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _Lot _self;
|
||||
final $Res Function(_Lot) _then;
|
||||
|
||||
/// Create a copy of Lot
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? lotId = freezed,Object? title = freezed,Object? description = freezed,}) {
|
||||
return _then(_Lot(
|
||||
lotId: freezed == lotId ? _self.lotId : lotId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,19 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'lot.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_Lot _$LotFromJson(Map<String, dynamic> json) => _Lot(
|
||||
lotId: json['lot_id'] as String?,
|
||||
title: json['title'] as String?,
|
||||
description: json['description'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LotToJson(_Lot instance) => <String, dynamic>{
|
||||
'lot_id': instance.lotId,
|
||||
'title': instance.title,
|
||||
'description': instance.description,
|
||||
};
|
||||
@@ -1,15 +1,22 @@
|
||||
// ignore_for_file: invalid_annotation_target
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:tm_app/data/services/model/organization/organization_address.dart';
|
||||
|
||||
part 'organization.freezed.dart';
|
||||
part 'organization.g.dart';
|
||||
|
||||
// AI-NOTE (for PR reviewer): Added company_id and a nested address
|
||||
// (OrganizationAddress) to surface buyer details on the tender-details page.
|
||||
// A dedicated OrganizationAddress type is used instead of the existing
|
||||
// `Address` model because the buyer address shape differs (city_name +
|
||||
// country_code only) and is unrelated to the user-profile Address.
|
||||
@freezed
|
||||
abstract class Organization with _$Organization {
|
||||
const factory Organization({
|
||||
required String? name,
|
||||
|
||||
@JsonKey(name: 'company_id') required String? companyId,
|
||||
required OrganizationAddress? address,
|
||||
}) = _Organization;
|
||||
|
||||
factory Organization.fromJson(Map<String, Object?> json) =>
|
||||
|
||||
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$Organization {
|
||||
|
||||
String? get name;
|
||||
String? get name;@JsonKey(name: 'company_id') String? get companyId; OrganizationAddress? get address;
|
||||
/// Create a copy of Organization
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -28,16 +28,16 @@ $OrganizationCopyWith<Organization> get copyWith => _$OrganizationCopyWithImpl<O
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is Organization&&(identical(other.name, name) || other.name == name));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is Organization&&(identical(other.name, name) || other.name == name)&&(identical(other.companyId, companyId) || other.companyId == companyId)&&(identical(other.address, address) || other.address == address));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,name);
|
||||
int get hashCode => Object.hash(runtimeType,name,companyId,address);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Organization(name: $name)';
|
||||
return 'Organization(name: $name, companyId: $companyId, address: $address)';
|
||||
}
|
||||
|
||||
|
||||
@@ -48,11 +48,11 @@ abstract mixin class $OrganizationCopyWith<$Res> {
|
||||
factory $OrganizationCopyWith(Organization value, $Res Function(Organization) _then) = _$OrganizationCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? name
|
||||
String? name,@JsonKey(name: 'company_id') String? companyId, OrganizationAddress? address
|
||||
});
|
||||
|
||||
|
||||
|
||||
$OrganizationAddressCopyWith<$Res>? get address;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -65,13 +65,27 @@ class _$OrganizationCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of Organization
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? name = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? name = freezed,Object? companyId = freezed,Object? address = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
as String?,companyId: freezed == companyId ? _self.companyId : companyId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,address: freezed == address ? _self.address : address // ignore: cast_nullable_to_non_nullable
|
||||
as OrganizationAddress?,
|
||||
));
|
||||
}
|
||||
/// Create a copy of Organization
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$OrganizationAddressCopyWith<$Res>? get address {
|
||||
if (_self.address == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $OrganizationAddressCopyWith<$Res>(_self.address!, (value) {
|
||||
return _then(_self.copyWith(address: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,10 +167,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? name)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? name, @JsonKey(name: 'company_id') String? companyId, OrganizationAddress? address)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _Organization() when $default != null:
|
||||
return $default(_that.name);case _:
|
||||
return $default(_that.name,_that.companyId,_that.address);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -174,10 +188,10 @@ return $default(_that.name);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? name) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? name, @JsonKey(name: 'company_id') String? companyId, OrganizationAddress? address) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _Organization():
|
||||
return $default(_that.name);case _:
|
||||
return $default(_that.name,_that.companyId,_that.address);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -194,10 +208,10 @@ return $default(_that.name);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? name)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? name, @JsonKey(name: 'company_id') String? companyId, OrganizationAddress? address)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _Organization() when $default != null:
|
||||
return $default(_that.name);case _:
|
||||
return $default(_that.name,_that.companyId,_that.address);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -209,10 +223,12 @@ return $default(_that.name);case _:
|
||||
@JsonSerializable()
|
||||
|
||||
class _Organization implements Organization {
|
||||
const _Organization({required this.name});
|
||||
const _Organization({required this.name, @JsonKey(name: 'company_id') required this.companyId, required this.address});
|
||||
factory _Organization.fromJson(Map<String, dynamic> json) => _$OrganizationFromJson(json);
|
||||
|
||||
@override final String? name;
|
||||
@override@JsonKey(name: 'company_id') final String? companyId;
|
||||
@override final OrganizationAddress? address;
|
||||
|
||||
/// Create a copy of Organization
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -227,16 +243,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Organization&&(identical(other.name, name) || other.name == name));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Organization&&(identical(other.name, name) || other.name == name)&&(identical(other.companyId, companyId) || other.companyId == companyId)&&(identical(other.address, address) || other.address == address));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,name);
|
||||
int get hashCode => Object.hash(runtimeType,name,companyId,address);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Organization(name: $name)';
|
||||
return 'Organization(name: $name, companyId: $companyId, address: $address)';
|
||||
}
|
||||
|
||||
|
||||
@@ -247,11 +263,11 @@ abstract mixin class _$OrganizationCopyWith<$Res> implements $OrganizationCopyWi
|
||||
factory _$OrganizationCopyWith(_Organization value, $Res Function(_Organization) _then) = __$OrganizationCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? name
|
||||
String? name,@JsonKey(name: 'company_id') String? companyId, OrganizationAddress? address
|
||||
});
|
||||
|
||||
|
||||
|
||||
@override $OrganizationAddressCopyWith<$Res>? get address;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -264,14 +280,28 @@ class __$OrganizationCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of Organization
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? name = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? name = freezed,Object? companyId = freezed,Object? address = freezed,}) {
|
||||
return _then(_Organization(
|
||||
name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
as String?,companyId: freezed == companyId ? _self.companyId : companyId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,address: freezed == address ? _self.address : address // ignore: cast_nullable_to_non_nullable
|
||||
as OrganizationAddress?,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of Organization
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$OrganizationAddressCopyWith<$Res>? get address {
|
||||
if (_self.address == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $OrganizationAddressCopyWith<$Res>(_self.address!, (value) {
|
||||
return _then(_self.copyWith(address: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// dart format on
|
||||
|
||||
@@ -7,7 +7,20 @@ part of 'organization.dart';
|
||||
// **************************************************************************
|
||||
|
||||
_Organization _$OrganizationFromJson(Map<String, dynamic> json) =>
|
||||
_Organization(name: json['name'] as String?);
|
||||
_Organization(
|
||||
name: json['name'] as String?,
|
||||
companyId: json['company_id'] as String?,
|
||||
address:
|
||||
json['address'] == null
|
||||
? null
|
||||
: OrganizationAddress.fromJson(
|
||||
json['address'] as Map<String, dynamic>,
|
||||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$OrganizationToJson(_Organization instance) =>
|
||||
<String, dynamic>{'name': instance.name};
|
||||
<String, dynamic>{
|
||||
'name': instance.name,
|
||||
'company_id': instance.companyId,
|
||||
'address': instance.address,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// ignore_for_file: invalid_annotation_target
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'organization_address.freezed.dart';
|
||||
part 'organization_address.g.dart';
|
||||
|
||||
// AI-NOTE (for PR reviewer): New model for the buyer_organization.address
|
||||
// object from the tender-details API. Kept separate from the existing profile
|
||||
// `Address` model because the shapes differ (this one only needs city_name and
|
||||
// country_code). Only the fields the UI shows are mapped.
|
||||
@freezed
|
||||
abstract class OrganizationAddress with _$OrganizationAddress {
|
||||
const factory OrganizationAddress({
|
||||
@JsonKey(name: 'city_name') required String? cityName,
|
||||
@JsonKey(name: 'country_code') required String? countryCode,
|
||||
}) = _OrganizationAddress;
|
||||
|
||||
factory OrganizationAddress.fromJson(Map<String, Object?> json) =>
|
||||
_$OrganizationAddressFromJson(json);
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'organization_address.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$OrganizationAddress {
|
||||
|
||||
@JsonKey(name: 'city_name') String? get cityName;@JsonKey(name: 'country_code') String? get countryCode;
|
||||
/// Create a copy of OrganizationAddress
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$OrganizationAddressCopyWith<OrganizationAddress> get copyWith => _$OrganizationAddressCopyWithImpl<OrganizationAddress>(this as OrganizationAddress, _$identity);
|
||||
|
||||
/// Serializes this OrganizationAddress to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is OrganizationAddress&&(identical(other.cityName, cityName) || other.cityName == cityName)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,cityName,countryCode);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'OrganizationAddress(cityName: $cityName, countryCode: $countryCode)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $OrganizationAddressCopyWith<$Res> {
|
||||
factory $OrganizationAddressCopyWith(OrganizationAddress value, $Res Function(OrganizationAddress) _then) = _$OrganizationAddressCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
@JsonKey(name: 'city_name') String? cityName,@JsonKey(name: 'country_code') String? countryCode
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$OrganizationAddressCopyWithImpl<$Res>
|
||||
implements $OrganizationAddressCopyWith<$Res> {
|
||||
_$OrganizationAddressCopyWithImpl(this._self, this._then);
|
||||
|
||||
final OrganizationAddress _self;
|
||||
final $Res Function(OrganizationAddress) _then;
|
||||
|
||||
/// Create a copy of OrganizationAddress
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? cityName = freezed,Object? countryCode = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
cityName: freezed == cityName ? _self.cityName : cityName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,countryCode: freezed == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [OrganizationAddress].
|
||||
extension OrganizationAddressPatterns on OrganizationAddress {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _OrganizationAddress value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _OrganizationAddress() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _OrganizationAddress value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _OrganizationAddress():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _OrganizationAddress value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _OrganizationAddress() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function(@JsonKey(name: 'city_name') String? cityName, @JsonKey(name: 'country_code') String? countryCode)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _OrganizationAddress() when $default != null:
|
||||
return $default(_that.cityName,_that.countryCode);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function(@JsonKey(name: 'city_name') String? cityName, @JsonKey(name: 'country_code') String? countryCode) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _OrganizationAddress():
|
||||
return $default(_that.cityName,_that.countryCode);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function(@JsonKey(name: 'city_name') String? cityName, @JsonKey(name: 'country_code') String? countryCode)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _OrganizationAddress() when $default != null:
|
||||
return $default(_that.cityName,_that.countryCode);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _OrganizationAddress implements OrganizationAddress {
|
||||
const _OrganizationAddress({@JsonKey(name: 'city_name') required this.cityName, @JsonKey(name: 'country_code') required this.countryCode});
|
||||
factory _OrganizationAddress.fromJson(Map<String, dynamic> json) => _$OrganizationAddressFromJson(json);
|
||||
|
||||
@override@JsonKey(name: 'city_name') final String? cityName;
|
||||
@override@JsonKey(name: 'country_code') final String? countryCode;
|
||||
|
||||
/// Create a copy of OrganizationAddress
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$OrganizationAddressCopyWith<_OrganizationAddress> get copyWith => __$OrganizationAddressCopyWithImpl<_OrganizationAddress>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$OrganizationAddressToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _OrganizationAddress&&(identical(other.cityName, cityName) || other.cityName == cityName)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,cityName,countryCode);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'OrganizationAddress(cityName: $cityName, countryCode: $countryCode)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$OrganizationAddressCopyWith<$Res> implements $OrganizationAddressCopyWith<$Res> {
|
||||
factory _$OrganizationAddressCopyWith(_OrganizationAddress value, $Res Function(_OrganizationAddress) _then) = __$OrganizationAddressCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
@JsonKey(name: 'city_name') String? cityName,@JsonKey(name: 'country_code') String? countryCode
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$OrganizationAddressCopyWithImpl<$Res>
|
||||
implements _$OrganizationAddressCopyWith<$Res> {
|
||||
__$OrganizationAddressCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _OrganizationAddress _self;
|
||||
final $Res Function(_OrganizationAddress) _then;
|
||||
|
||||
/// Create a copy of OrganizationAddress
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? cityName = freezed,Object? countryCode = freezed,}) {
|
||||
return _then(_OrganizationAddress(
|
||||
cityName: freezed == cityName ? _self.cityName : cityName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,countryCode: freezed == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,20 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'organization_address.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_OrganizationAddress _$OrganizationAddressFromJson(Map<String, dynamic> json) =>
|
||||
_OrganizationAddress(
|
||||
cityName: json['city_name'] as String?,
|
||||
countryCode: json['country_code'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$OrganizationAddressToJson(
|
||||
_OrganizationAddress instance,
|
||||
) => <String, dynamic>{
|
||||
'city_name': instance.cityName,
|
||||
'country_code': instance.countryCode,
|
||||
};
|
||||
@@ -2,11 +2,19 @@
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:tm_app/core/utils/date_utils.dart';
|
||||
import 'package:tm_app/data/services/model/lot/lot.dart';
|
||||
import 'package:tm_app/data/services/model/organization/organization.dart';
|
||||
|
||||
part 'tender_data.freezed.dart';
|
||||
part 'tender_data.g.dart';
|
||||
|
||||
// AI-NOTE (for PR reviewer): New fields were added to mirror the
|
||||
// /tenders/details/:id response so the tender-details page can show them:
|
||||
// notice_type_code, form_type, notice_language_code, issue_date, issue_time,
|
||||
// lots, official_languages. issue_date/issue_time reuse unixTimestampFromJson
|
||||
// (epoch seconds, tolerant of ms/string) like the other timestamp fields. All
|
||||
// fields are nullable to stay resilient to partial API payloads. Freezed/json
|
||||
// codegen (.freezed.dart/.g.dart) was regenerated for these.
|
||||
@freezed
|
||||
abstract class TenderData with _$TenderData {
|
||||
const factory TenderData({
|
||||
@@ -16,6 +24,13 @@ abstract class TenderData with _$TenderData {
|
||||
@JsonKey(name: 'tender_id') required String? tenderId,
|
||||
@JsonKey(name: 'notice_publication_id')
|
||||
required String? noticePublicationId,
|
||||
@JsonKey(name: 'notice_type_code') required String? noticeTypeCode,
|
||||
@JsonKey(name: 'form_type') required String? formType,
|
||||
@JsonKey(name: 'notice_language_code') required String? noticeLanguageCode,
|
||||
@JsonKey(name: 'issue_date', fromJson: unixTimestampFromJson)
|
||||
required int? issueDate,
|
||||
@JsonKey(name: 'issue_time', fromJson: unixTimestampFromJson)
|
||||
required int? issueTime,
|
||||
@JsonKey(name: 'publication_date', fromJson: unixTimestampFromJson)
|
||||
required int? publicationDate,
|
||||
required String? title,
|
||||
@@ -37,6 +52,9 @@ abstract class TenderData with _$TenderData {
|
||||
@JsonKey(name: 'duration_unit') required String? durationUnit,
|
||||
@JsonKey(name: 'buyer_organization')
|
||||
required Organization? buyerOrganization,
|
||||
required List<Lot>? lots,
|
||||
@JsonKey(name: 'official_languages')
|
||||
required List<String>? officialLanguages,
|
||||
required String? status,
|
||||
}) = _TenderData;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$TenderData {
|
||||
|
||||
bool? get success; String? get message; String? get id;@JsonKey(name: 'tender_id') String? get tenderId;@JsonKey(name: 'notice_publication_id') String? get noticePublicationId;@JsonKey(name: 'publication_date') int? get publicationDate; String? get title; String? get description;@JsonKey(name: 'procurement_type_code') String? get procurementTypeCode;@JsonKey(name: 'procedure_code') String? get procedureCode;@JsonKey(name: 'estimated_value') int? get estimatedValue; String? get currency; String? get duration;@JsonKey(name: 'tender_deadline') int? get tenderDeadline;@JsonKey(name: 'submission_deadline') int? get submissionDeadline;@JsonKey(name: 'application_deadline') int? get applicationDeadline;@JsonKey(name: 'submission_url') String? get submissionUrl;@JsonKey(name: 'country_code') String? get countryCode;@JsonKey(name: 'duration_unit') String? get durationUnit;@JsonKey(name: 'buyer_organization') Organization? get buyerOrganization; String? get status;
|
||||
bool? get success; String? get message; String? get id;@JsonKey(name: 'tender_id') String? get tenderId;@JsonKey(name: 'notice_publication_id') String? get noticePublicationId;@JsonKey(name: 'notice_type_code') String? get noticeTypeCode;@JsonKey(name: 'form_type') String? get formType;@JsonKey(name: 'notice_language_code') String? get noticeLanguageCode;@JsonKey(name: 'issue_date', fromJson: unixTimestampFromJson) int? get issueDate;@JsonKey(name: 'issue_time', fromJson: unixTimestampFromJson) int? get issueTime;@JsonKey(name: 'publication_date', fromJson: unixTimestampFromJson) int? get publicationDate; String? get title; String? get description;@JsonKey(name: 'procurement_type_code') String? get procurementTypeCode;@JsonKey(name: 'procedure_code') String? get procedureCode;@JsonKey(name: 'estimated_value') int? get estimatedValue; String? get currency; String? get duration;@JsonKey(name: 'tender_deadline', fromJson: unixTimestampFromJson) int? get tenderDeadline;@JsonKey(name: 'submission_deadline', fromJson: unixTimestampFromJson) int? get submissionDeadline;@JsonKey(name: 'application_deadline', fromJson: unixTimestampFromJson) int? get applicationDeadline;@JsonKey(name: 'submission_url') String? get submissionUrl;@JsonKey(name: 'country_code') String? get countryCode;@JsonKey(name: 'duration_unit') String? get durationUnit;@JsonKey(name: 'buyer_organization') Organization? get buyerOrganization; List<Lot>? get lots;@JsonKey(name: 'official_languages') List<String>? get officialLanguages; String? get status;
|
||||
/// Create a copy of TenderData
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -28,16 +28,16 @@ $TenderDataCopyWith<TenderData> get copyWith => _$TenderDataCopyWithImpl<TenderD
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TenderData&&(identical(other.success, success) || other.success == success)&&(identical(other.message, message) || other.message == message)&&(identical(other.id, id) || other.id == id)&&(identical(other.tenderId, tenderId) || other.tenderId == tenderId)&&(identical(other.noticePublicationId, noticePublicationId) || other.noticePublicationId == noticePublicationId)&&(identical(other.publicationDate, publicationDate) || other.publicationDate == publicationDate)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.procurementTypeCode, procurementTypeCode) || other.procurementTypeCode == procurementTypeCode)&&(identical(other.procedureCode, procedureCode) || other.procedureCode == procedureCode)&&(identical(other.estimatedValue, estimatedValue) || other.estimatedValue == estimatedValue)&&(identical(other.currency, currency) || other.currency == currency)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.tenderDeadline, tenderDeadline) || other.tenderDeadline == tenderDeadline)&&(identical(other.submissionDeadline, submissionDeadline) || other.submissionDeadline == submissionDeadline)&&(identical(other.applicationDeadline, applicationDeadline) || other.applicationDeadline == applicationDeadline)&&(identical(other.submissionUrl, submissionUrl) || other.submissionUrl == submissionUrl)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.durationUnit, durationUnit) || other.durationUnit == durationUnit)&&(identical(other.buyerOrganization, buyerOrganization) || other.buyerOrganization == buyerOrganization)&&(identical(other.status, status) || other.status == status));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TenderData&&(identical(other.success, success) || other.success == success)&&(identical(other.message, message) || other.message == message)&&(identical(other.id, id) || other.id == id)&&(identical(other.tenderId, tenderId) || other.tenderId == tenderId)&&(identical(other.noticePublicationId, noticePublicationId) || other.noticePublicationId == noticePublicationId)&&(identical(other.noticeTypeCode, noticeTypeCode) || other.noticeTypeCode == noticeTypeCode)&&(identical(other.formType, formType) || other.formType == formType)&&(identical(other.noticeLanguageCode, noticeLanguageCode) || other.noticeLanguageCode == noticeLanguageCode)&&(identical(other.issueDate, issueDate) || other.issueDate == issueDate)&&(identical(other.issueTime, issueTime) || other.issueTime == issueTime)&&(identical(other.publicationDate, publicationDate) || other.publicationDate == publicationDate)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.procurementTypeCode, procurementTypeCode) || other.procurementTypeCode == procurementTypeCode)&&(identical(other.procedureCode, procedureCode) || other.procedureCode == procedureCode)&&(identical(other.estimatedValue, estimatedValue) || other.estimatedValue == estimatedValue)&&(identical(other.currency, currency) || other.currency == currency)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.tenderDeadline, tenderDeadline) || other.tenderDeadline == tenderDeadline)&&(identical(other.submissionDeadline, submissionDeadline) || other.submissionDeadline == submissionDeadline)&&(identical(other.applicationDeadline, applicationDeadline) || other.applicationDeadline == applicationDeadline)&&(identical(other.submissionUrl, submissionUrl) || other.submissionUrl == submissionUrl)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.durationUnit, durationUnit) || other.durationUnit == durationUnit)&&(identical(other.buyerOrganization, buyerOrganization) || other.buyerOrganization == buyerOrganization)&&const DeepCollectionEquality().equals(other.lots, lots)&&const DeepCollectionEquality().equals(other.officialLanguages, officialLanguages)&&(identical(other.status, status) || other.status == status));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hashAll([runtimeType,success,message,id,tenderId,noticePublicationId,publicationDate,title,description,procurementTypeCode,procedureCode,estimatedValue,currency,duration,tenderDeadline,submissionDeadline,applicationDeadline,submissionUrl,countryCode,durationUnit,buyerOrganization,status]);
|
||||
int get hashCode => Object.hashAll([runtimeType,success,message,id,tenderId,noticePublicationId,noticeTypeCode,formType,noticeLanguageCode,issueDate,issueTime,publicationDate,title,description,procurementTypeCode,procedureCode,estimatedValue,currency,duration,tenderDeadline,submissionDeadline,applicationDeadline,submissionUrl,countryCode,durationUnit,buyerOrganization,const DeepCollectionEquality().hash(lots),const DeepCollectionEquality().hash(officialLanguages),status]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TenderData(success: $success, message: $message, id: $id, tenderId: $tenderId, noticePublicationId: $noticePublicationId, publicationDate: $publicationDate, title: $title, description: $description, procurementTypeCode: $procurementTypeCode, procedureCode: $procedureCode, estimatedValue: $estimatedValue, currency: $currency, duration: $duration, tenderDeadline: $tenderDeadline, submissionDeadline: $submissionDeadline, applicationDeadline: $applicationDeadline, submissionUrl: $submissionUrl, countryCode: $countryCode, durationUnit: $durationUnit, buyerOrganization: $buyerOrganization, status: $status)';
|
||||
return 'TenderData(success: $success, message: $message, id: $id, tenderId: $tenderId, noticePublicationId: $noticePublicationId, noticeTypeCode: $noticeTypeCode, formType: $formType, noticeLanguageCode: $noticeLanguageCode, issueDate: $issueDate, issueTime: $issueTime, publicationDate: $publicationDate, title: $title, description: $description, procurementTypeCode: $procurementTypeCode, procedureCode: $procedureCode, estimatedValue: $estimatedValue, currency: $currency, duration: $duration, tenderDeadline: $tenderDeadline, submissionDeadline: $submissionDeadline, applicationDeadline: $applicationDeadline, submissionUrl: $submissionUrl, countryCode: $countryCode, durationUnit: $durationUnit, buyerOrganization: $buyerOrganization, lots: $lots, officialLanguages: $officialLanguages, status: $status)';
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ abstract mixin class $TenderDataCopyWith<$Res> {
|
||||
factory $TenderDataCopyWith(TenderData value, $Res Function(TenderData) _then) = _$TenderDataCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool? success, String? message, String? id,@JsonKey(name: 'tender_id') String? tenderId,@JsonKey(name: 'notice_publication_id') String? noticePublicationId,@JsonKey(name: 'publication_date') int? publicationDate, String? title, String? description,@JsonKey(name: 'procurement_type_code') String? procurementTypeCode,@JsonKey(name: 'procedure_code') String? procedureCode,@JsonKey(name: 'estimated_value') int? estimatedValue, String? currency, String? duration,@JsonKey(name: 'tender_deadline') int? tenderDeadline,@JsonKey(name: 'submission_deadline') int? submissionDeadline,@JsonKey(name: 'application_deadline') int? applicationDeadline,@JsonKey(name: 'submission_url') String? submissionUrl,@JsonKey(name: 'country_code') String? countryCode,@JsonKey(name: 'duration_unit') String? durationUnit,@JsonKey(name: 'buyer_organization') Organization? buyerOrganization, String? status
|
||||
bool? success, String? message, String? id,@JsonKey(name: 'tender_id') String? tenderId,@JsonKey(name: 'notice_publication_id') String? noticePublicationId,@JsonKey(name: 'notice_type_code') String? noticeTypeCode,@JsonKey(name: 'form_type') String? formType,@JsonKey(name: 'notice_language_code') String? noticeLanguageCode,@JsonKey(name: 'issue_date', fromJson: unixTimestampFromJson) int? issueDate,@JsonKey(name: 'issue_time', fromJson: unixTimestampFromJson) int? issueTime,@JsonKey(name: 'publication_date', fromJson: unixTimestampFromJson) int? publicationDate, String? title, String? description,@JsonKey(name: 'procurement_type_code') String? procurementTypeCode,@JsonKey(name: 'procedure_code') String? procedureCode,@JsonKey(name: 'estimated_value') int? estimatedValue, String? currency, String? duration,@JsonKey(name: 'tender_deadline', fromJson: unixTimestampFromJson) int? tenderDeadline,@JsonKey(name: 'submission_deadline', fromJson: unixTimestampFromJson) int? submissionDeadline,@JsonKey(name: 'application_deadline', fromJson: unixTimestampFromJson) int? applicationDeadline,@JsonKey(name: 'submission_url') String? submissionUrl,@JsonKey(name: 'country_code') String? countryCode,@JsonKey(name: 'duration_unit') String? durationUnit,@JsonKey(name: 'buyer_organization') Organization? buyerOrganization, List<Lot>? lots,@JsonKey(name: 'official_languages') List<String>? officialLanguages, String? status
|
||||
});
|
||||
|
||||
|
||||
@@ -65,14 +65,19 @@ class _$TenderDataCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of TenderData
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? success = freezed,Object? message = freezed,Object? id = freezed,Object? tenderId = freezed,Object? noticePublicationId = freezed,Object? publicationDate = freezed,Object? title = freezed,Object? description = freezed,Object? procurementTypeCode = freezed,Object? procedureCode = freezed,Object? estimatedValue = freezed,Object? currency = freezed,Object? duration = freezed,Object? tenderDeadline = freezed,Object? submissionDeadline = freezed,Object? applicationDeadline = freezed,Object? submissionUrl = freezed,Object? countryCode = freezed,Object? durationUnit = freezed,Object? buyerOrganization = freezed,Object? status = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? success = freezed,Object? message = freezed,Object? id = freezed,Object? tenderId = freezed,Object? noticePublicationId = freezed,Object? noticeTypeCode = freezed,Object? formType = freezed,Object? noticeLanguageCode = freezed,Object? issueDate = freezed,Object? issueTime = freezed,Object? publicationDate = freezed,Object? title = freezed,Object? description = freezed,Object? procurementTypeCode = freezed,Object? procedureCode = freezed,Object? estimatedValue = freezed,Object? currency = freezed,Object? duration = freezed,Object? tenderDeadline = freezed,Object? submissionDeadline = freezed,Object? applicationDeadline = freezed,Object? submissionUrl = freezed,Object? countryCode = freezed,Object? durationUnit = freezed,Object? buyerOrganization = freezed,Object? lots = freezed,Object? officialLanguages = freezed,Object? status = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
|
||||
as String?,id: freezed == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String?,tenderId: freezed == tenderId ? _self.tenderId : tenderId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,noticePublicationId: freezed == noticePublicationId ? _self.noticePublicationId : noticePublicationId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,publicationDate: freezed == publicationDate ? _self.publicationDate : publicationDate // ignore: cast_nullable_to_non_nullable
|
||||
as String?,noticeTypeCode: freezed == noticeTypeCode ? _self.noticeTypeCode : noticeTypeCode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,formType: freezed == formType ? _self.formType : formType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,noticeLanguageCode: freezed == noticeLanguageCode ? _self.noticeLanguageCode : noticeLanguageCode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,issueDate: freezed == issueDate ? _self.issueDate : issueDate // ignore: cast_nullable_to_non_nullable
|
||||
as int?,issueTime: freezed == issueTime ? _self.issueTime : issueTime // ignore: cast_nullable_to_non_nullable
|
||||
as int?,publicationDate: freezed == publicationDate ? _self.publicationDate : publicationDate // ignore: cast_nullable_to_non_nullable
|
||||
as int?,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,procurementTypeCode: freezed == procurementTypeCode ? _self.procurementTypeCode : procurementTypeCode // ignore: cast_nullable_to_non_nullable
|
||||
@@ -87,7 +92,9 @@ as int?,submissionUrl: freezed == submissionUrl ? _self.submissionUrl : submissi
|
||||
as String?,countryCode: freezed == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,durationUnit: freezed == durationUnit ? _self.durationUnit : durationUnit // ignore: cast_nullable_to_non_nullable
|
||||
as String?,buyerOrganization: freezed == buyerOrganization ? _self.buyerOrganization : buyerOrganization // ignore: cast_nullable_to_non_nullable
|
||||
as Organization?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||
as Organization?,lots: freezed == lots ? _self.lots : lots // ignore: cast_nullable_to_non_nullable
|
||||
as List<Lot>?,officialLanguages: freezed == officialLanguages ? _self.officialLanguages : officialLanguages // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
@@ -185,10 +192,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool? success, String? message, String? id, @JsonKey(name: 'tender_id') String? tenderId, @JsonKey(name: 'notice_publication_id') String? noticePublicationId, @JsonKey(name: 'publication_date') int? publicationDate, String? title, String? description, @JsonKey(name: 'procurement_type_code') String? procurementTypeCode, @JsonKey(name: 'procedure_code') String? procedureCode, @JsonKey(name: 'estimated_value') int? estimatedValue, String? currency, String? duration, @JsonKey(name: 'tender_deadline') int? tenderDeadline, @JsonKey(name: 'submission_deadline') int? submissionDeadline, @JsonKey(name: 'application_deadline') int? applicationDeadline, @JsonKey(name: 'submission_url') String? submissionUrl, @JsonKey(name: 'country_code') String? countryCode, @JsonKey(name: 'duration_unit') String? durationUnit, @JsonKey(name: 'buyer_organization') Organization? buyerOrganization, String? status)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool? success, String? message, String? id, @JsonKey(name: 'tender_id') String? tenderId, @JsonKey(name: 'notice_publication_id') String? noticePublicationId, @JsonKey(name: 'notice_type_code') String? noticeTypeCode, @JsonKey(name: 'form_type') String? formType, @JsonKey(name: 'notice_language_code') String? noticeLanguageCode, @JsonKey(name: 'issue_date', fromJson: unixTimestampFromJson) int? issueDate, @JsonKey(name: 'issue_time', fromJson: unixTimestampFromJson) int? issueTime, @JsonKey(name: 'publication_date', fromJson: unixTimestampFromJson) int? publicationDate, String? title, String? description, @JsonKey(name: 'procurement_type_code') String? procurementTypeCode, @JsonKey(name: 'procedure_code') String? procedureCode, @JsonKey(name: 'estimated_value') int? estimatedValue, String? currency, String? duration, @JsonKey(name: 'tender_deadline', fromJson: unixTimestampFromJson) int? tenderDeadline, @JsonKey(name: 'submission_deadline', fromJson: unixTimestampFromJson) int? submissionDeadline, @JsonKey(name: 'application_deadline', fromJson: unixTimestampFromJson) int? applicationDeadline, @JsonKey(name: 'submission_url') String? submissionUrl, @JsonKey(name: 'country_code') String? countryCode, @JsonKey(name: 'duration_unit') String? durationUnit, @JsonKey(name: 'buyer_organization') Organization? buyerOrganization, List<Lot>? lots, @JsonKey(name: 'official_languages') List<String>? officialLanguages, String? status)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TenderData() when $default != null:
|
||||
return $default(_that.success,_that.message,_that.id,_that.tenderId,_that.noticePublicationId,_that.publicationDate,_that.title,_that.description,_that.procurementTypeCode,_that.procedureCode,_that.estimatedValue,_that.currency,_that.duration,_that.tenderDeadline,_that.submissionDeadline,_that.applicationDeadline,_that.submissionUrl,_that.countryCode,_that.durationUnit,_that.buyerOrganization,_that.status);case _:
|
||||
return $default(_that.success,_that.message,_that.id,_that.tenderId,_that.noticePublicationId,_that.noticeTypeCode,_that.formType,_that.noticeLanguageCode,_that.issueDate,_that.issueTime,_that.publicationDate,_that.title,_that.description,_that.procurementTypeCode,_that.procedureCode,_that.estimatedValue,_that.currency,_that.duration,_that.tenderDeadline,_that.submissionDeadline,_that.applicationDeadline,_that.submissionUrl,_that.countryCode,_that.durationUnit,_that.buyerOrganization,_that.lots,_that.officialLanguages,_that.status);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -206,10 +213,10 @@ return $default(_that.success,_that.message,_that.id,_that.tenderId,_that.notice
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool? success, String? message, String? id, @JsonKey(name: 'tender_id') String? tenderId, @JsonKey(name: 'notice_publication_id') String? noticePublicationId, @JsonKey(name: 'publication_date') int? publicationDate, String? title, String? description, @JsonKey(name: 'procurement_type_code') String? procurementTypeCode, @JsonKey(name: 'procedure_code') String? procedureCode, @JsonKey(name: 'estimated_value') int? estimatedValue, String? currency, String? duration, @JsonKey(name: 'tender_deadline') int? tenderDeadline, @JsonKey(name: 'submission_deadline') int? submissionDeadline, @JsonKey(name: 'application_deadline') int? applicationDeadline, @JsonKey(name: 'submission_url') String? submissionUrl, @JsonKey(name: 'country_code') String? countryCode, @JsonKey(name: 'duration_unit') String? durationUnit, @JsonKey(name: 'buyer_organization') Organization? buyerOrganization, String? status) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool? success, String? message, String? id, @JsonKey(name: 'tender_id') String? tenderId, @JsonKey(name: 'notice_publication_id') String? noticePublicationId, @JsonKey(name: 'notice_type_code') String? noticeTypeCode, @JsonKey(name: 'form_type') String? formType, @JsonKey(name: 'notice_language_code') String? noticeLanguageCode, @JsonKey(name: 'issue_date', fromJson: unixTimestampFromJson) int? issueDate, @JsonKey(name: 'issue_time', fromJson: unixTimestampFromJson) int? issueTime, @JsonKey(name: 'publication_date', fromJson: unixTimestampFromJson) int? publicationDate, String? title, String? description, @JsonKey(name: 'procurement_type_code') String? procurementTypeCode, @JsonKey(name: 'procedure_code') String? procedureCode, @JsonKey(name: 'estimated_value') int? estimatedValue, String? currency, String? duration, @JsonKey(name: 'tender_deadline', fromJson: unixTimestampFromJson) int? tenderDeadline, @JsonKey(name: 'submission_deadline', fromJson: unixTimestampFromJson) int? submissionDeadline, @JsonKey(name: 'application_deadline', fromJson: unixTimestampFromJson) int? applicationDeadline, @JsonKey(name: 'submission_url') String? submissionUrl, @JsonKey(name: 'country_code') String? countryCode, @JsonKey(name: 'duration_unit') String? durationUnit, @JsonKey(name: 'buyer_organization') Organization? buyerOrganization, List<Lot>? lots, @JsonKey(name: 'official_languages') List<String>? officialLanguages, String? status) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TenderData():
|
||||
return $default(_that.success,_that.message,_that.id,_that.tenderId,_that.noticePublicationId,_that.publicationDate,_that.title,_that.description,_that.procurementTypeCode,_that.procedureCode,_that.estimatedValue,_that.currency,_that.duration,_that.tenderDeadline,_that.submissionDeadline,_that.applicationDeadline,_that.submissionUrl,_that.countryCode,_that.durationUnit,_that.buyerOrganization,_that.status);case _:
|
||||
return $default(_that.success,_that.message,_that.id,_that.tenderId,_that.noticePublicationId,_that.noticeTypeCode,_that.formType,_that.noticeLanguageCode,_that.issueDate,_that.issueTime,_that.publicationDate,_that.title,_that.description,_that.procurementTypeCode,_that.procedureCode,_that.estimatedValue,_that.currency,_that.duration,_that.tenderDeadline,_that.submissionDeadline,_that.applicationDeadline,_that.submissionUrl,_that.countryCode,_that.durationUnit,_that.buyerOrganization,_that.lots,_that.officialLanguages,_that.status);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -226,10 +233,10 @@ return $default(_that.success,_that.message,_that.id,_that.tenderId,_that.notice
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool? success, String? message, String? id, @JsonKey(name: 'tender_id') String? tenderId, @JsonKey(name: 'notice_publication_id') String? noticePublicationId, @JsonKey(name: 'publication_date') int? publicationDate, String? title, String? description, @JsonKey(name: 'procurement_type_code') String? procurementTypeCode, @JsonKey(name: 'procedure_code') String? procedureCode, @JsonKey(name: 'estimated_value') int? estimatedValue, String? currency, String? duration, @JsonKey(name: 'tender_deadline') int? tenderDeadline, @JsonKey(name: 'submission_deadline') int? submissionDeadline, @JsonKey(name: 'application_deadline') int? applicationDeadline, @JsonKey(name: 'submission_url') String? submissionUrl, @JsonKey(name: 'country_code') String? countryCode, @JsonKey(name: 'duration_unit') String? durationUnit, @JsonKey(name: 'buyer_organization') Organization? buyerOrganization, String? status)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool? success, String? message, String? id, @JsonKey(name: 'tender_id') String? tenderId, @JsonKey(name: 'notice_publication_id') String? noticePublicationId, @JsonKey(name: 'notice_type_code') String? noticeTypeCode, @JsonKey(name: 'form_type') String? formType, @JsonKey(name: 'notice_language_code') String? noticeLanguageCode, @JsonKey(name: 'issue_date', fromJson: unixTimestampFromJson) int? issueDate, @JsonKey(name: 'issue_time', fromJson: unixTimestampFromJson) int? issueTime, @JsonKey(name: 'publication_date', fromJson: unixTimestampFromJson) int? publicationDate, String? title, String? description, @JsonKey(name: 'procurement_type_code') String? procurementTypeCode, @JsonKey(name: 'procedure_code') String? procedureCode, @JsonKey(name: 'estimated_value') int? estimatedValue, String? currency, String? duration, @JsonKey(name: 'tender_deadline', fromJson: unixTimestampFromJson) int? tenderDeadline, @JsonKey(name: 'submission_deadline', fromJson: unixTimestampFromJson) int? submissionDeadline, @JsonKey(name: 'application_deadline', fromJson: unixTimestampFromJson) int? applicationDeadline, @JsonKey(name: 'submission_url') String? submissionUrl, @JsonKey(name: 'country_code') String? countryCode, @JsonKey(name: 'duration_unit') String? durationUnit, @JsonKey(name: 'buyer_organization') Organization? buyerOrganization, List<Lot>? lots, @JsonKey(name: 'official_languages') List<String>? officialLanguages, String? status)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _TenderData() when $default != null:
|
||||
return $default(_that.success,_that.message,_that.id,_that.tenderId,_that.noticePublicationId,_that.publicationDate,_that.title,_that.description,_that.procurementTypeCode,_that.procedureCode,_that.estimatedValue,_that.currency,_that.duration,_that.tenderDeadline,_that.submissionDeadline,_that.applicationDeadline,_that.submissionUrl,_that.countryCode,_that.durationUnit,_that.buyerOrganization,_that.status);case _:
|
||||
return $default(_that.success,_that.message,_that.id,_that.tenderId,_that.noticePublicationId,_that.noticeTypeCode,_that.formType,_that.noticeLanguageCode,_that.issueDate,_that.issueTime,_that.publicationDate,_that.title,_that.description,_that.procurementTypeCode,_that.procedureCode,_that.estimatedValue,_that.currency,_that.duration,_that.tenderDeadline,_that.submissionDeadline,_that.applicationDeadline,_that.submissionUrl,_that.countryCode,_that.durationUnit,_that.buyerOrganization,_that.lots,_that.officialLanguages,_that.status);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -241,7 +248,7 @@ return $default(_that.success,_that.message,_that.id,_that.tenderId,_that.notice
|
||||
@JsonSerializable()
|
||||
|
||||
class _TenderData implements TenderData {
|
||||
const _TenderData({required this.success, required this.message, required this.id, @JsonKey(name: 'tender_id') required this.tenderId, @JsonKey(name: 'notice_publication_id') required this.noticePublicationId, @JsonKey(name: 'publication_date') required this.publicationDate, required this.title, required this.description, @JsonKey(name: 'procurement_type_code') required this.procurementTypeCode, @JsonKey(name: 'procedure_code') required this.procedureCode, @JsonKey(name: 'estimated_value') required this.estimatedValue, required this.currency, required this.duration, @JsonKey(name: 'tender_deadline') required this.tenderDeadline, @JsonKey(name: 'submission_deadline') required this.submissionDeadline, @JsonKey(name: 'application_deadline') required this.applicationDeadline, @JsonKey(name: 'submission_url') required this.submissionUrl, @JsonKey(name: 'country_code') required this.countryCode, @JsonKey(name: 'duration_unit') required this.durationUnit, @JsonKey(name: 'buyer_organization') required this.buyerOrganization, required this.status});
|
||||
const _TenderData({required this.success, required this.message, required this.id, @JsonKey(name: 'tender_id') required this.tenderId, @JsonKey(name: 'notice_publication_id') required this.noticePublicationId, @JsonKey(name: 'notice_type_code') required this.noticeTypeCode, @JsonKey(name: 'form_type') required this.formType, @JsonKey(name: 'notice_language_code') required this.noticeLanguageCode, @JsonKey(name: 'issue_date', fromJson: unixTimestampFromJson) required this.issueDate, @JsonKey(name: 'issue_time', fromJson: unixTimestampFromJson) required this.issueTime, @JsonKey(name: 'publication_date', fromJson: unixTimestampFromJson) required this.publicationDate, required this.title, required this.description, @JsonKey(name: 'procurement_type_code') required this.procurementTypeCode, @JsonKey(name: 'procedure_code') required this.procedureCode, @JsonKey(name: 'estimated_value') required this.estimatedValue, required this.currency, required this.duration, @JsonKey(name: 'tender_deadline', fromJson: unixTimestampFromJson) required this.tenderDeadline, @JsonKey(name: 'submission_deadline', fromJson: unixTimestampFromJson) required this.submissionDeadline, @JsonKey(name: 'application_deadline', fromJson: unixTimestampFromJson) required this.applicationDeadline, @JsonKey(name: 'submission_url') required this.submissionUrl, @JsonKey(name: 'country_code') required this.countryCode, @JsonKey(name: 'duration_unit') required this.durationUnit, @JsonKey(name: 'buyer_organization') required this.buyerOrganization, required final List<Lot>? lots, @JsonKey(name: 'official_languages') required final List<String>? officialLanguages, required this.status}): _lots = lots,_officialLanguages = officialLanguages;
|
||||
factory _TenderData.fromJson(Map<String, dynamic> json) => _$TenderDataFromJson(json);
|
||||
|
||||
@override final bool? success;
|
||||
@@ -249,7 +256,12 @@ class _TenderData implements TenderData {
|
||||
@override final String? id;
|
||||
@override@JsonKey(name: 'tender_id') final String? tenderId;
|
||||
@override@JsonKey(name: 'notice_publication_id') final String? noticePublicationId;
|
||||
@override@JsonKey(name: 'publication_date') final int? publicationDate;
|
||||
@override@JsonKey(name: 'notice_type_code') final String? noticeTypeCode;
|
||||
@override@JsonKey(name: 'form_type') final String? formType;
|
||||
@override@JsonKey(name: 'notice_language_code') final String? noticeLanguageCode;
|
||||
@override@JsonKey(name: 'issue_date', fromJson: unixTimestampFromJson) final int? issueDate;
|
||||
@override@JsonKey(name: 'issue_time', fromJson: unixTimestampFromJson) final int? issueTime;
|
||||
@override@JsonKey(name: 'publication_date', fromJson: unixTimestampFromJson) final int? publicationDate;
|
||||
@override final String? title;
|
||||
@override final String? description;
|
||||
@override@JsonKey(name: 'procurement_type_code') final String? procurementTypeCode;
|
||||
@@ -257,13 +269,31 @@ class _TenderData implements TenderData {
|
||||
@override@JsonKey(name: 'estimated_value') final int? estimatedValue;
|
||||
@override final String? currency;
|
||||
@override final String? duration;
|
||||
@override@JsonKey(name: 'tender_deadline') final int? tenderDeadline;
|
||||
@override@JsonKey(name: 'submission_deadline') final int? submissionDeadline;
|
||||
@override@JsonKey(name: 'application_deadline') final int? applicationDeadline;
|
||||
@override@JsonKey(name: 'tender_deadline', fromJson: unixTimestampFromJson) final int? tenderDeadline;
|
||||
@override@JsonKey(name: 'submission_deadline', fromJson: unixTimestampFromJson) final int? submissionDeadline;
|
||||
@override@JsonKey(name: 'application_deadline', fromJson: unixTimestampFromJson) final int? applicationDeadline;
|
||||
@override@JsonKey(name: 'submission_url') final String? submissionUrl;
|
||||
@override@JsonKey(name: 'country_code') final String? countryCode;
|
||||
@override@JsonKey(name: 'duration_unit') final String? durationUnit;
|
||||
@override@JsonKey(name: 'buyer_organization') final Organization? buyerOrganization;
|
||||
final List<Lot>? _lots;
|
||||
@override List<Lot>? get lots {
|
||||
final value = _lots;
|
||||
if (value == null) return null;
|
||||
if (_lots is EqualUnmodifiableListView) return _lots;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(value);
|
||||
}
|
||||
|
||||
final List<String>? _officialLanguages;
|
||||
@override@JsonKey(name: 'official_languages') List<String>? get officialLanguages {
|
||||
final value = _officialLanguages;
|
||||
if (value == null) return null;
|
||||
if (_officialLanguages is EqualUnmodifiableListView) return _officialLanguages;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(value);
|
||||
}
|
||||
|
||||
@override final String? status;
|
||||
|
||||
/// Create a copy of TenderData
|
||||
@@ -279,16 +309,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TenderData&&(identical(other.success, success) || other.success == success)&&(identical(other.message, message) || other.message == message)&&(identical(other.id, id) || other.id == id)&&(identical(other.tenderId, tenderId) || other.tenderId == tenderId)&&(identical(other.noticePublicationId, noticePublicationId) || other.noticePublicationId == noticePublicationId)&&(identical(other.publicationDate, publicationDate) || other.publicationDate == publicationDate)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.procurementTypeCode, procurementTypeCode) || other.procurementTypeCode == procurementTypeCode)&&(identical(other.procedureCode, procedureCode) || other.procedureCode == procedureCode)&&(identical(other.estimatedValue, estimatedValue) || other.estimatedValue == estimatedValue)&&(identical(other.currency, currency) || other.currency == currency)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.tenderDeadline, tenderDeadline) || other.tenderDeadline == tenderDeadline)&&(identical(other.submissionDeadline, submissionDeadline) || other.submissionDeadline == submissionDeadline)&&(identical(other.applicationDeadline, applicationDeadline) || other.applicationDeadline == applicationDeadline)&&(identical(other.submissionUrl, submissionUrl) || other.submissionUrl == submissionUrl)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.durationUnit, durationUnit) || other.durationUnit == durationUnit)&&(identical(other.buyerOrganization, buyerOrganization) || other.buyerOrganization == buyerOrganization)&&(identical(other.status, status) || other.status == status));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TenderData&&(identical(other.success, success) || other.success == success)&&(identical(other.message, message) || other.message == message)&&(identical(other.id, id) || other.id == id)&&(identical(other.tenderId, tenderId) || other.tenderId == tenderId)&&(identical(other.noticePublicationId, noticePublicationId) || other.noticePublicationId == noticePublicationId)&&(identical(other.noticeTypeCode, noticeTypeCode) || other.noticeTypeCode == noticeTypeCode)&&(identical(other.formType, formType) || other.formType == formType)&&(identical(other.noticeLanguageCode, noticeLanguageCode) || other.noticeLanguageCode == noticeLanguageCode)&&(identical(other.issueDate, issueDate) || other.issueDate == issueDate)&&(identical(other.issueTime, issueTime) || other.issueTime == issueTime)&&(identical(other.publicationDate, publicationDate) || other.publicationDate == publicationDate)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.procurementTypeCode, procurementTypeCode) || other.procurementTypeCode == procurementTypeCode)&&(identical(other.procedureCode, procedureCode) || other.procedureCode == procedureCode)&&(identical(other.estimatedValue, estimatedValue) || other.estimatedValue == estimatedValue)&&(identical(other.currency, currency) || other.currency == currency)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.tenderDeadline, tenderDeadline) || other.tenderDeadline == tenderDeadline)&&(identical(other.submissionDeadline, submissionDeadline) || other.submissionDeadline == submissionDeadline)&&(identical(other.applicationDeadline, applicationDeadline) || other.applicationDeadline == applicationDeadline)&&(identical(other.submissionUrl, submissionUrl) || other.submissionUrl == submissionUrl)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.durationUnit, durationUnit) || other.durationUnit == durationUnit)&&(identical(other.buyerOrganization, buyerOrganization) || other.buyerOrganization == buyerOrganization)&&const DeepCollectionEquality().equals(other._lots, _lots)&&const DeepCollectionEquality().equals(other._officialLanguages, _officialLanguages)&&(identical(other.status, status) || other.status == status));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hashAll([runtimeType,success,message,id,tenderId,noticePublicationId,publicationDate,title,description,procurementTypeCode,procedureCode,estimatedValue,currency,duration,tenderDeadline,submissionDeadline,applicationDeadline,submissionUrl,countryCode,durationUnit,buyerOrganization,status]);
|
||||
int get hashCode => Object.hashAll([runtimeType,success,message,id,tenderId,noticePublicationId,noticeTypeCode,formType,noticeLanguageCode,issueDate,issueTime,publicationDate,title,description,procurementTypeCode,procedureCode,estimatedValue,currency,duration,tenderDeadline,submissionDeadline,applicationDeadline,submissionUrl,countryCode,durationUnit,buyerOrganization,const DeepCollectionEquality().hash(_lots),const DeepCollectionEquality().hash(_officialLanguages),status]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TenderData(success: $success, message: $message, id: $id, tenderId: $tenderId, noticePublicationId: $noticePublicationId, publicationDate: $publicationDate, title: $title, description: $description, procurementTypeCode: $procurementTypeCode, procedureCode: $procedureCode, estimatedValue: $estimatedValue, currency: $currency, duration: $duration, tenderDeadline: $tenderDeadline, submissionDeadline: $submissionDeadline, applicationDeadline: $applicationDeadline, submissionUrl: $submissionUrl, countryCode: $countryCode, durationUnit: $durationUnit, buyerOrganization: $buyerOrganization, status: $status)';
|
||||
return 'TenderData(success: $success, message: $message, id: $id, tenderId: $tenderId, noticePublicationId: $noticePublicationId, noticeTypeCode: $noticeTypeCode, formType: $formType, noticeLanguageCode: $noticeLanguageCode, issueDate: $issueDate, issueTime: $issueTime, publicationDate: $publicationDate, title: $title, description: $description, procurementTypeCode: $procurementTypeCode, procedureCode: $procedureCode, estimatedValue: $estimatedValue, currency: $currency, duration: $duration, tenderDeadline: $tenderDeadline, submissionDeadline: $submissionDeadline, applicationDeadline: $applicationDeadline, submissionUrl: $submissionUrl, countryCode: $countryCode, durationUnit: $durationUnit, buyerOrganization: $buyerOrganization, lots: $lots, officialLanguages: $officialLanguages, status: $status)';
|
||||
}
|
||||
|
||||
|
||||
@@ -299,7 +329,7 @@ abstract mixin class _$TenderDataCopyWith<$Res> implements $TenderDataCopyWith<$
|
||||
factory _$TenderDataCopyWith(_TenderData value, $Res Function(_TenderData) _then) = __$TenderDataCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool? success, String? message, String? id,@JsonKey(name: 'tender_id') String? tenderId,@JsonKey(name: 'notice_publication_id') String? noticePublicationId,@JsonKey(name: 'publication_date') int? publicationDate, String? title, String? description,@JsonKey(name: 'procurement_type_code') String? procurementTypeCode,@JsonKey(name: 'procedure_code') String? procedureCode,@JsonKey(name: 'estimated_value') int? estimatedValue, String? currency, String? duration,@JsonKey(name: 'tender_deadline') int? tenderDeadline,@JsonKey(name: 'submission_deadline') int? submissionDeadline,@JsonKey(name: 'application_deadline') int? applicationDeadline,@JsonKey(name: 'submission_url') String? submissionUrl,@JsonKey(name: 'country_code') String? countryCode,@JsonKey(name: 'duration_unit') String? durationUnit,@JsonKey(name: 'buyer_organization') Organization? buyerOrganization, String? status
|
||||
bool? success, String? message, String? id,@JsonKey(name: 'tender_id') String? tenderId,@JsonKey(name: 'notice_publication_id') String? noticePublicationId,@JsonKey(name: 'notice_type_code') String? noticeTypeCode,@JsonKey(name: 'form_type') String? formType,@JsonKey(name: 'notice_language_code') String? noticeLanguageCode,@JsonKey(name: 'issue_date', fromJson: unixTimestampFromJson) int? issueDate,@JsonKey(name: 'issue_time', fromJson: unixTimestampFromJson) int? issueTime,@JsonKey(name: 'publication_date', fromJson: unixTimestampFromJson) int? publicationDate, String? title, String? description,@JsonKey(name: 'procurement_type_code') String? procurementTypeCode,@JsonKey(name: 'procedure_code') String? procedureCode,@JsonKey(name: 'estimated_value') int? estimatedValue, String? currency, String? duration,@JsonKey(name: 'tender_deadline', fromJson: unixTimestampFromJson) int? tenderDeadline,@JsonKey(name: 'submission_deadline', fromJson: unixTimestampFromJson) int? submissionDeadline,@JsonKey(name: 'application_deadline', fromJson: unixTimestampFromJson) int? applicationDeadline,@JsonKey(name: 'submission_url') String? submissionUrl,@JsonKey(name: 'country_code') String? countryCode,@JsonKey(name: 'duration_unit') String? durationUnit,@JsonKey(name: 'buyer_organization') Organization? buyerOrganization, List<Lot>? lots,@JsonKey(name: 'official_languages') List<String>? officialLanguages, String? status
|
||||
});
|
||||
|
||||
|
||||
@@ -316,14 +346,19 @@ class __$TenderDataCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of TenderData
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? success = freezed,Object? message = freezed,Object? id = freezed,Object? tenderId = freezed,Object? noticePublicationId = freezed,Object? publicationDate = freezed,Object? title = freezed,Object? description = freezed,Object? procurementTypeCode = freezed,Object? procedureCode = freezed,Object? estimatedValue = freezed,Object? currency = freezed,Object? duration = freezed,Object? tenderDeadline = freezed,Object? submissionDeadline = freezed,Object? applicationDeadline = freezed,Object? submissionUrl = freezed,Object? countryCode = freezed,Object? durationUnit = freezed,Object? buyerOrganization = freezed,Object? status = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? success = freezed,Object? message = freezed,Object? id = freezed,Object? tenderId = freezed,Object? noticePublicationId = freezed,Object? noticeTypeCode = freezed,Object? formType = freezed,Object? noticeLanguageCode = freezed,Object? issueDate = freezed,Object? issueTime = freezed,Object? publicationDate = freezed,Object? title = freezed,Object? description = freezed,Object? procurementTypeCode = freezed,Object? procedureCode = freezed,Object? estimatedValue = freezed,Object? currency = freezed,Object? duration = freezed,Object? tenderDeadline = freezed,Object? submissionDeadline = freezed,Object? applicationDeadline = freezed,Object? submissionUrl = freezed,Object? countryCode = freezed,Object? durationUnit = freezed,Object? buyerOrganization = freezed,Object? lots = freezed,Object? officialLanguages = freezed,Object? status = freezed,}) {
|
||||
return _then(_TenderData(
|
||||
success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
|
||||
as String?,id: freezed == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String?,tenderId: freezed == tenderId ? _self.tenderId : tenderId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,noticePublicationId: freezed == noticePublicationId ? _self.noticePublicationId : noticePublicationId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,publicationDate: freezed == publicationDate ? _self.publicationDate : publicationDate // ignore: cast_nullable_to_non_nullable
|
||||
as String?,noticeTypeCode: freezed == noticeTypeCode ? _self.noticeTypeCode : noticeTypeCode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,formType: freezed == formType ? _self.formType : formType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,noticeLanguageCode: freezed == noticeLanguageCode ? _self.noticeLanguageCode : noticeLanguageCode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,issueDate: freezed == issueDate ? _self.issueDate : issueDate // ignore: cast_nullable_to_non_nullable
|
||||
as int?,issueTime: freezed == issueTime ? _self.issueTime : issueTime // ignore: cast_nullable_to_non_nullable
|
||||
as int?,publicationDate: freezed == publicationDate ? _self.publicationDate : publicationDate // ignore: cast_nullable_to_non_nullable
|
||||
as int?,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,procurementTypeCode: freezed == procurementTypeCode ? _self.procurementTypeCode : procurementTypeCode // ignore: cast_nullable_to_non_nullable
|
||||
@@ -338,7 +373,9 @@ as int?,submissionUrl: freezed == submissionUrl ? _self.submissionUrl : submissi
|
||||
as String?,countryCode: freezed == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,durationUnit: freezed == durationUnit ? _self.durationUnit : durationUnit // ignore: cast_nullable_to_non_nullable
|
||||
as String?,buyerOrganization: freezed == buyerOrganization ? _self.buyerOrganization : buyerOrganization // ignore: cast_nullable_to_non_nullable
|
||||
as Organization?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||
as Organization?,lots: freezed == lots ? _self._lots : lots // ignore: cast_nullable_to_non_nullable
|
||||
as List<Lot>?,officialLanguages: freezed == officialLanguages ? _self._officialLanguages : officialLanguages // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -12,6 +12,11 @@ _TenderData _$TenderDataFromJson(Map<String, dynamic> json) => _TenderData(
|
||||
id: json['id'] as String?,
|
||||
tenderId: json['tender_id'] as String?,
|
||||
noticePublicationId: json['notice_publication_id'] as String?,
|
||||
noticeTypeCode: json['notice_type_code'] as String?,
|
||||
formType: json['form_type'] as String?,
|
||||
noticeLanguageCode: json['notice_language_code'] as String?,
|
||||
issueDate: unixTimestampFromJson(json['issue_date']),
|
||||
issueTime: unixTimestampFromJson(json['issue_time']),
|
||||
publicationDate: unixTimestampFromJson(json['publication_date']),
|
||||
title: json['title'] as String?,
|
||||
description: json['description'] as String?,
|
||||
@@ -32,6 +37,14 @@ _TenderData _$TenderDataFromJson(Map<String, dynamic> json) => _TenderData(
|
||||
: Organization.fromJson(
|
||||
json['buyer_organization'] as Map<String, dynamic>,
|
||||
),
|
||||
lots:
|
||||
(json['lots'] as List<dynamic>?)
|
||||
?.map((e) => Lot.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
officialLanguages:
|
||||
(json['official_languages'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList(),
|
||||
status: json['status'] as String?,
|
||||
);
|
||||
|
||||
@@ -42,6 +55,11 @@ Map<String, dynamic> _$TenderDataToJson(_TenderData instance) =>
|
||||
'id': instance.id,
|
||||
'tender_id': instance.tenderId,
|
||||
'notice_publication_id': instance.noticePublicationId,
|
||||
'notice_type_code': instance.noticeTypeCode,
|
||||
'form_type': instance.formType,
|
||||
'notice_language_code': instance.noticeLanguageCode,
|
||||
'issue_date': instance.issueDate,
|
||||
'issue_time': instance.issueTime,
|
||||
'publication_date': instance.publicationDate,
|
||||
'title': instance.title,
|
||||
'description': instance.description,
|
||||
@@ -57,5 +75,7 @@ Map<String, dynamic> _$TenderDataToJson(_TenderData instance) =>
|
||||
'country_code': instance.countryCode,
|
||||
'duration_unit': instance.durationUnit,
|
||||
'buyer_organization': instance.buyerOrganization,
|
||||
'lots': instance.lots,
|
||||
'official_languages': instance.officialLanguages,
|
||||
'status': instance.status,
|
||||
};
|
||||
|
||||
@@ -11,6 +11,38 @@
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class $AssetsFontsGen {
|
||||
const $AssetsFontsGen();
|
||||
|
||||
/// File path: assets/fonts/Roboto-Black.ttf
|
||||
String get robotoBlack => 'assets/fonts/Roboto-Black.ttf';
|
||||
|
||||
/// File path: assets/fonts/Roboto-Bold.ttf
|
||||
String get robotoBold => 'assets/fonts/Roboto-Bold.ttf';
|
||||
|
||||
/// File path: assets/fonts/Roboto-Light.ttf
|
||||
String get robotoLight => 'assets/fonts/Roboto-Light.ttf';
|
||||
|
||||
/// File path: assets/fonts/Roboto-Medium.ttf
|
||||
String get robotoMedium => 'assets/fonts/Roboto-Medium.ttf';
|
||||
|
||||
/// File path: assets/fonts/Roboto-Regular.ttf
|
||||
String get robotoRegular => 'assets/fonts/Roboto-Regular.ttf';
|
||||
|
||||
/// File path: assets/fonts/Roboto-Thin.ttf
|
||||
String get robotoThin => 'assets/fonts/Roboto-Thin.ttf';
|
||||
|
||||
/// List of all assets
|
||||
List<String> get values => [
|
||||
robotoBlack,
|
||||
robotoBold,
|
||||
robotoLight,
|
||||
robotoMedium,
|
||||
robotoRegular,
|
||||
robotoThin,
|
||||
];
|
||||
}
|
||||
|
||||
class $AssetsIconsGen {
|
||||
const $AssetsIconsGen();
|
||||
|
||||
@@ -301,6 +333,7 @@ class $AssetsSvgsGen {
|
||||
class Assets {
|
||||
const Assets._();
|
||||
|
||||
static const $AssetsFontsGen fonts = $AssetsFontsGen();
|
||||
static const $AssetsIconsGen icons = $AssetsIconsGen();
|
||||
static const $AssetsPngsGen pngs = $AssetsPngsGen();
|
||||
static const $AssetsSvgsGen svgs = $AssetsSvgsGen();
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// dart format width=80
|
||||
/// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
/// *****************************************************
|
||||
/// FlutterGen
|
||||
/// *****************************************************
|
||||
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: deprecated_member_use,directives_ordering,implicit_dynamic_list_literal,unnecessary_import
|
||||
|
||||
class FontFamily {
|
||||
FontFamily._();
|
||||
|
||||
/// Font family: Roboto
|
||||
static const String roboto = 'Roboto';
|
||||
}
|
||||
@@ -39,42 +39,12 @@ class TendersViewModel with ChangeNotifier {
|
||||
|
||||
static const int _pageSize = 10;
|
||||
|
||||
// --- Offset pagination state ---
|
||||
// --- Infinite-scroll offset state ---
|
||||
int _currentOffset = 0;
|
||||
int _lastValidPages = 1;
|
||||
int _lastValidLimit = _pageSize;
|
||||
|
||||
bool _hasMoreData = true;
|
||||
bool get hasMoreData => _hasMoreData;
|
||||
|
||||
/// 0-based current page index.
|
||||
int get currentPageIndex {
|
||||
final meta = _tendersResponse?.meta;
|
||||
final limit = meta?.limit ?? _lastValidLimit;
|
||||
|
||||
if (limit > 0) {
|
||||
return _currentOffset ~/ limit;
|
||||
}
|
||||
if (meta?.offset != null && limit > 0) {
|
||||
return meta!.offset! ~/ limit;
|
||||
}
|
||||
if (meta?.page != null) {
|
||||
return meta!.page! - 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// 1-based current page (for display).
|
||||
int get currentPage => currentPageIndex + 1;
|
||||
|
||||
int get totalPages {
|
||||
final pages = _tendersResponse?.meta?.pages;
|
||||
if (pages != null && pages > 0) {
|
||||
return pages;
|
||||
}
|
||||
return _lastValidPages;
|
||||
}
|
||||
|
||||
// Filter States
|
||||
DateTimeRange? selectedDateRange;
|
||||
String selectedStatus = 'All';
|
||||
@@ -233,12 +203,6 @@ class TendersViewModel with ChangeNotifier {
|
||||
case Ok<TendersResponse>():
|
||||
_tendersResponse = result.value;
|
||||
final meta = _tendersResponse?.meta;
|
||||
if (meta?.pages != null && meta!.pages! > 0) {
|
||||
_lastValidPages = meta.pages!;
|
||||
}
|
||||
if (meta?.limit != null && meta!.limit! > 0) {
|
||||
_lastValidLimit = meta.limit!;
|
||||
}
|
||||
if (meta?.offset != null) {
|
||||
_currentOffset = meta!.offset!;
|
||||
}
|
||||
@@ -299,12 +263,6 @@ class TendersViewModel with ChangeNotifier {
|
||||
data: result.value.data?.copyWith(tenders: combined),
|
||||
);
|
||||
final newMeta = result.value.meta;
|
||||
if (newMeta?.pages != null && newMeta!.pages! > 0) {
|
||||
_lastValidPages = newMeta.pages!;
|
||||
}
|
||||
if (newMeta?.limit != null && newMeta!.limit! > 0) {
|
||||
_lastValidLimit = newMeta.limit!;
|
||||
}
|
||||
_hasMoreData =
|
||||
newMeta?.hasMore ?? (newTenders.length >= _pageSize);
|
||||
} else {
|
||||
@@ -492,54 +450,4 @@ class TendersViewModel with ChangeNotifier {
|
||||
sortOrder = '';
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// [selected] is the absolute 0-based target page index.
|
||||
Future<void> handlePaginationChange(int selected) async {
|
||||
if (selected < 0) {
|
||||
return;
|
||||
}
|
||||
final maxPage = totalPages - 1;
|
||||
if (maxPage >= 0 && selected > maxPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (selected == currentPageIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
await _goToOffsetPage(selected);
|
||||
}
|
||||
|
||||
Future<void> _goToOffsetPage(int pageIndex) async {
|
||||
final limit = _tendersResponse?.meta?.limit ?? _pageSize;
|
||||
_currentOffset = pageIndex * limit;
|
||||
await _fetchPage();
|
||||
}
|
||||
|
||||
Future<void> _fetchPage() async {
|
||||
_isLoading = true;
|
||||
notifyListeners();
|
||||
|
||||
final result = await _tendersRepository.getTenders(
|
||||
limit: _pageSize,
|
||||
offset: _currentOffset,
|
||||
query: _searchQuery,
|
||||
sortBy: sortBy,
|
||||
sortOrder: sortOrder,
|
||||
publicationDateFrom: startDateUnix,
|
||||
publicationDateTo: endDateUnix,
|
||||
);
|
||||
|
||||
_handleListResult(result, fetchAllFeedbacks: true);
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
_errorMessage = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Kept for backwards compatibility with existing callers.
|
||||
/// Accepts a 1-based page number.
|
||||
void jumpToPage(int page) {
|
||||
handlePaginationChange(page - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ import 'package:tm_app/core/theme/colors.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/view_models/tender_detail_view_model.dart';
|
||||
import 'package:tm_app/views/detail/widgets/tender_detail_action.dart';
|
||||
import 'package:tm_app/views/detail/widgets/tender_detail_card.dart';
|
||||
// AI-NOTE (for PR reviewer): Import kept (commented) — the TenderDetailCard
|
||||
// (static "profile match / incomplete resume" card) is disabled, not removed.
|
||||
// import 'package:tm_app/views/detail/widgets/tender_detail_card.dart';
|
||||
import 'package:tm_app/views/detail/widgets/tender_detail_header.dart';
|
||||
|
||||
import '../../../core/constants/tender_approval_status.dart';
|
||||
@@ -121,8 +123,10 @@ class _TenderDetailDesktopPageState extends State<TenderDetailDesktopPage> {
|
||||
detail: detail,
|
||||
),
|
||||
SizedBox(height: 32.0.h()),
|
||||
TenderDetailCard(detail: detail),
|
||||
SizedBox(height: 24.0.h()),
|
||||
// AI-NOTE (for PR reviewer): Static mock card
|
||||
// disabled (kept for future) — hard-coded data.
|
||||
// TenderDetailCard(detail: detail),
|
||||
// SizedBox(height: 24.0.h()),
|
||||
TenderDetailActions(
|
||||
isScreenBig: true,
|
||||
detail: detail,
|
||||
|
||||
@@ -5,7 +5,9 @@ import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/view_models/tender_detail_view_model.dart';
|
||||
import 'package:tm_app/views/detail/strings/tender_details_strings.dart';
|
||||
import 'package:tm_app/views/detail/widgets/tender_detail_action.dart';
|
||||
import 'package:tm_app/views/detail/widgets/tender_detail_card.dart';
|
||||
// AI-NOTE (for PR reviewer): Import kept (commented) — the TenderDetailCard
|
||||
// (static "profile match / incomplete resume" card) is disabled, not removed.
|
||||
// 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/shared/tender_app_bar.dart';
|
||||
|
||||
@@ -112,8 +114,10 @@ class _TenderDetailMobilePageState extends State<TenderDetailMobilePage> {
|
||||
children: [
|
||||
TenderDetailHeader(isScreenBig: false, detail: detail),
|
||||
SizedBox(height: 24.0.h()),
|
||||
TenderDetailCard(detail: detail),
|
||||
SizedBox(height: 24.0.h()),
|
||||
// AI-NOTE (for PR reviewer): Static mock card disabled (kept
|
||||
// for future use) — shows hard-coded profile-match data.
|
||||
// TenderDetailCard(detail: detail),
|
||||
// SizedBox(height: 24.0.h()),
|
||||
TenderDetailActions(
|
||||
isScreenBig: false,
|
||||
detail: detail,
|
||||
|
||||
@@ -4,7 +4,9 @@ import 'package:tm_app/core/theme/colors.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/view_models/tender_detail_view_model.dart';
|
||||
import 'package:tm_app/views/detail/widgets/tender_detail_action.dart';
|
||||
import 'package:tm_app/views/detail/widgets/tender_detail_card.dart';
|
||||
// AI-NOTE (for PR reviewer): Import kept (commented) — the TenderDetailCard
|
||||
// (static "profile match / incomplete resume" card) is disabled, not removed.
|
||||
// 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/shared/tablet_navigation_widget.dart';
|
||||
|
||||
@@ -123,8 +125,10 @@ class _TenderDetailTabletPageState extends State<TenderDetailTabletPage> {
|
||||
SizedBox(height: 28.0.h()),
|
||||
TenderDetailHeader(isScreenBig: true, detail: detail),
|
||||
SizedBox(height: 28.0.h()),
|
||||
TenderDetailCard(detail: detail),
|
||||
SizedBox(height: 24.0.h()),
|
||||
// AI-NOTE (for PR reviewer): Static mock card disabled
|
||||
// (kept for future) — hard-coded profile-match data.
|
||||
// TenderDetailCard(detail: detail),
|
||||
// SizedBox(height: 24.0.h()),
|
||||
TenderDetailActions(
|
||||
isScreenBig: true,
|
||||
detail: detail,
|
||||
|
||||
@@ -42,4 +42,33 @@ class TenderDetailsStrings {
|
||||
static const String requestSuccessfullyRegistered =
|
||||
'Your request has been successfully registered.';
|
||||
static const String confirmAndClose = 'Confirm and close';
|
||||
// AI-NOTE (for PR reviewer): Formal toast copy shown after the user confirms
|
||||
// the Accept/submission modal (see tender_detail_action.dart).
|
||||
static const String submissionReceived =
|
||||
'Thank you. We have received your submission and will be in touch with you shortly.';
|
||||
|
||||
// AI-NOTE (for PR reviewer): Field labels added for the rewritten
|
||||
// tender-details info section (one per backend field rendered there).
|
||||
// Tender detail field labels
|
||||
static const String noticeTypeCode = 'Notice Type';
|
||||
static const String formType = 'Form Type';
|
||||
static const String noticeLanguageCode = 'Notice Language';
|
||||
static const String issueDate = 'Issue Date';
|
||||
static const String issueTime = 'Issue Time';
|
||||
static const String procedureCode = 'Procedure';
|
||||
static const String durationLabel = 'Duration';
|
||||
static const String publicationDate = 'Publication Date';
|
||||
static const String tenderDeadlineDate = 'Tender Deadline';
|
||||
static const String submissionDeadline = 'Submission Deadline';
|
||||
static const String applicationDeadline = 'Application Deadline';
|
||||
static const String countryCode = 'Country';
|
||||
static const String buyerName = 'Buyer';
|
||||
static const String companyId = 'Company ID';
|
||||
static const String buyerCity = 'City';
|
||||
static const String buyerCountry = 'Buyer Country';
|
||||
static const String officialLanguages = 'Official Languages';
|
||||
static const String status = 'Status';
|
||||
static const String tenderId = 'Tender ID';
|
||||
static const String lots = 'Lots';
|
||||
static const String lotId = 'Lot ID';
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// AI-NOTE (for PR reviewer): This widget is currently unused — it was only used
|
||||
// by the static mock sections in TenderDetailHeader, which are now commented
|
||||
// out. It is intentionally KEPT for future use, not deleted. Safe to ignore as
|
||||
// dead code for now.
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
|
||||
@@ -4,14 +4,19 @@ import 'package:tm_app/core/theme/colors.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/view_models/auth_view_model.dart';
|
||||
import 'package:tm_app/view_models/tender_detail_view_model.dart';
|
||||
import 'package:tm_app/views/detail/widgets/meeting_time_bottom_sheet.dart';
|
||||
import 'package:tm_app/views/detail/widgets/meeting_time_dialog.dart';
|
||||
// AI-NOTE (for PR reviewer): These three imports are kept (commented) because
|
||||
// the post-confirm navigation flow they supported (documents-completion routes
|
||||
// + meeting-time modals) is preserved as commented-out code below, not deleted.
|
||||
// The Accept flow now just shows a confirmation toast instead. Re-enable these
|
||||
// imports if/when the navigation flow is reinstated.
|
||||
// import 'package:tm_app/views/detail/widgets/meeting_time_bottom_sheet.dart';
|
||||
// import 'package:tm_app/views/detail/widgets/meeting_time_dialog.dart';
|
||||
import 'package:tm_app/views/shared/base_button.dart';
|
||||
import 'package:tm_app/views/shared/select_submission_bottom_sheet.dart';
|
||||
|
||||
import '../../../core/constants/tender_approval_status.dart';
|
||||
import '../../../core/constants/tender_submision_mode.dart';
|
||||
import '../../../core/routes/app_routes.dart';
|
||||
// import '../../../core/routes/app_routes.dart';
|
||||
import '../../../core/utils/app_toast.dart';
|
||||
import '../../../data/services/model/tender_data/tender_data.dart';
|
||||
import '../../shared/select_submission_dialog.dart';
|
||||
@@ -68,38 +73,37 @@ class _TenderDetailActionsState extends State<TenderDetailActions> {
|
||||
builder: (context) {
|
||||
return SelectSubmissionBottomSheet(
|
||||
onConfirm: (String value) {
|
||||
if (value ==
|
||||
TenderSubmissionMode.selfApply.value) {
|
||||
// viewModel.submitTenderApproval(
|
||||
// AI-NOTE (for PR reviewer): New behavior —
|
||||
// confirming the submission modal now just
|
||||
// shows a confirmation toast (no API call, no
|
||||
// navigation), per product request. The prior
|
||||
// navigation flow is preserved below for future
|
||||
// use and is intentionally NOT deleted.
|
||||
_showSubmissionReceivedToast();
|
||||
// if (value ==
|
||||
// TenderSubmissionMode.selfApply.value) {
|
||||
// // viewModel.submitTenderApproval(
|
||||
// // tenderId: widget.detail.id!,
|
||||
// // submissionMode: value,
|
||||
// // );
|
||||
// CompletionOfDocumentsRouteData(
|
||||
// tenderId: widget.detail.id!,
|
||||
// submissionMode: value,
|
||||
// ).push(context);
|
||||
// } else if (value ==
|
||||
// TenderSubmissionMode.partnership.value) {
|
||||
// Future.delayed(Duration.zero, () {
|
||||
// if (context.mounted) {
|
||||
// showModalBottomSheet(
|
||||
// context: context,
|
||||
// builder: (_) {
|
||||
// return MeetingTimeBottomSheet(
|
||||
// onConfirm: (value) {},
|
||||
// );
|
||||
|
||||
CompletionOfDocumentsRouteData(
|
||||
tenderId: widget.detail.id!,
|
||||
).push(context);
|
||||
} else if (value ==
|
||||
TenderSubmissionMode.partnership.value) {
|
||||
Future.delayed(Duration.zero, () {
|
||||
if (context.mounted) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
|
||||
builder: (_) {
|
||||
return MeetingTimeBottomSheet(
|
||||
onConfirm: (value) {
|
||||
// AppToast.success(
|
||||
// context,
|
||||
// TenderDetailsStrings
|
||||
// .meetingTimeSuccessfullySet,
|
||||
// },
|
||||
// );
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
},
|
||||
);
|
||||
},
|
||||
@@ -143,6 +147,17 @@ class _TenderDetailActionsState extends State<TenderDetailActions> {
|
||||
);
|
||||
}
|
||||
|
||||
// AI-NOTE (for PR reviewer): New helper added for the Accept flow. Shows a
|
||||
// success toast confirming the submission was received. Guards on `mounted`
|
||||
// because it runs from a modal callback after the sheet/dialog is popped.
|
||||
// Uses the State's own context (stable page context), not the popped modal's.
|
||||
void _showSubmissionReceivedToast() {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
AppToast.success(context, TenderDetailsStrings.submissionReceived);
|
||||
}
|
||||
|
||||
Row _webActions(Role userRole) {
|
||||
return Row(
|
||||
children: [
|
||||
@@ -206,33 +221,37 @@ class _TenderDetailActionsState extends State<TenderDetailActions> {
|
||||
builder: (context) {
|
||||
return SelectSubmissionDialog(
|
||||
onConfirm: (String value) {
|
||||
if (value ==
|
||||
TenderSubmissionMode.selfApply.value) {
|
||||
if (context.mounted) {
|
||||
if (userRole == Role.analyst) {
|
||||
const FinalCompletionOfDocumentsRouteData()
|
||||
.push(context);
|
||||
} else {
|
||||
CompletionOfDocumentsRouteData(
|
||||
tenderId: widget.detail.id!,
|
||||
).push(context);
|
||||
}
|
||||
}
|
||||
} else if (value ==
|
||||
TenderSubmissionMode.partnership.value) {
|
||||
Future.delayed(Duration.zero, () {
|
||||
if (context.mounted) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MeetingTimeDialog(
|
||||
onConfirm: (value) {},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
// AI-NOTE (for PR reviewer): New behavior —
|
||||
// toast only (no API/navigation). Old role-aware
|
||||
// navigation preserved below for future use.
|
||||
_showSubmissionReceivedToast();
|
||||
// if (value ==
|
||||
// TenderSubmissionMode.selfApply.value) {
|
||||
// if (context.mounted) {
|
||||
// if (userRole == Role.analyst) {
|
||||
// const FinalCompletionOfDocumentsRouteData()
|
||||
// .push(context);
|
||||
// } else {
|
||||
// CompletionOfDocumentsRouteData(
|
||||
// tenderId: widget.detail.id!,
|
||||
// ).push(context);
|
||||
// }
|
||||
// }
|
||||
// } else if (value ==
|
||||
// TenderSubmissionMode.partnership.value) {
|
||||
// Future.delayed(Duration.zero, () {
|
||||
// if (context.mounted) {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (context) {
|
||||
// return MeetingTimeDialog(
|
||||
// onConfirm: (value) {},
|
||||
// );
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
},
|
||||
);
|
||||
},
|
||||
@@ -242,41 +261,34 @@ class _TenderDetailActionsState extends State<TenderDetailActions> {
|
||||
builder: (context) {
|
||||
return SelectSubmissionBottomSheet(
|
||||
onConfirm: (String value) {
|
||||
if (value ==
|
||||
TenderSubmissionMode.selfApply.value) {
|
||||
// viewModel.submitTenderApproval(
|
||||
// tenderId: widget.detail.id!,
|
||||
// submissionMode: value,
|
||||
// );
|
||||
if (context.mounted) {
|
||||
const FinalCompletionOfDocumentsRouteData()
|
||||
.push(context);
|
||||
}
|
||||
} else if (value ==
|
||||
TenderSubmissionMode.partnership.value) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MeetingTimeBottomSheet(
|
||||
onConfirm: (value) {
|
||||
AppToast.success(
|
||||
context,
|
||||
TenderDetailsStrings
|
||||
.meetingTimeSuccessfullySet,
|
||||
);
|
||||
},
|
||||
);
|
||||
// return MeetingTimeDialog(
|
||||
// onConfirm: (String value) {
|
||||
// AI-NOTE (for PR reviewer): New behavior —
|
||||
// toast only (no API/navigation). Old flow
|
||||
// (final-completion route + meeting-time
|
||||
// bottom sheet) preserved below for future use.
|
||||
_showSubmissionReceivedToast();
|
||||
// if (value ==
|
||||
// TenderSubmissionMode.selfApply.value) {
|
||||
// if (context.mounted) {
|
||||
// const CompletionOfDocumentsRouteData()
|
||||
// const FinalCompletionOfDocumentsRouteData()
|
||||
// .push(context);
|
||||
// }
|
||||
// } else if (value ==
|
||||
// TenderSubmissionMode.partnership.value) {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (context) {
|
||||
// return MeetingTimeBottomSheet(
|
||||
// onConfirm: (value) {
|
||||
// AppToast.success(
|
||||
// context,
|
||||
// TenderDetailsStrings
|
||||
// .meetingTimeSuccessfullySet,
|
||||
// );
|
||||
// },
|
||||
// );
|
||||
},
|
||||
);
|
||||
}
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// AI-NOTE (for PR reviewer): This widget is currently unused — its usages on the
|
||||
// tender-details pages are commented out (it renders a static/mock "profile
|
||||
// match 75% + incomplete resume" card, not backend data). It is intentionally
|
||||
// KEPT for future use, not deleted. Safe to ignore as dead code for now.
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tm_app/core/theme/colors.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
|
||||
@@ -9,7 +9,12 @@ import 'package:tm_app/views/detail/widgets/tender_detail_info_section.dart';
|
||||
import '../../../core/constants/assets.dart';
|
||||
import '../../shared/flag.dart';
|
||||
import '../strings/tender_details_strings.dart';
|
||||
import 'detail_drop_down.dart';
|
||||
// AI-NOTE (for PR reviewer): Import is intentionally kept but commented out.
|
||||
// The static/mock sections it supports (key risks, winning chance, project id,
|
||||
// service/requirements/background dropdowns) were disabled — NOT removed —
|
||||
// because they were hard-coded placeholders, not backend data. Re-enable this
|
||||
// import together with those sections once the API provides that data.
|
||||
// import 'detail_drop_down.dart';
|
||||
|
||||
class TenderDetailHeader extends StatelessWidget {
|
||||
final bool isScreenBig;
|
||||
@@ -41,44 +46,32 @@ class TenderDetailHeader extends StatelessWidget {
|
||||
SizedBox(height: 16.0.h()),
|
||||
_locationBudgetRow(),
|
||||
SizedBox(height: 24.0.h()),
|
||||
_projectId(),
|
||||
SizedBox(height: 12.0.h()),
|
||||
_winningChanceAndDificulty(),
|
||||
SizedBox(height: 24.0.h()),
|
||||
_keyRisksDropDown(),
|
||||
SizedBox(height: 24.0.h()),
|
||||
// AI-NOTE (for PR reviewer): The following mock sections are disabled
|
||||
// on purpose (kept for future use). They render hard-coded values, not
|
||||
// backend data, so they are commented out rather than deleted.
|
||||
// _projectId(),
|
||||
// SizedBox(height: 12.0.h()),
|
||||
// _winningChanceAndDificulty(),
|
||||
// SizedBox(height: 24.0.h()),
|
||||
// _keyRisksDropDown(),
|
||||
// SizedBox(height: 24.0.h()),
|
||||
Divider(color: AppColors.grey20),
|
||||
TenderDetailInfoSection(isScreenBig: isScreenBig, detail: detail),
|
||||
SizedBox(height: 24.0.h()),
|
||||
_overViewTitle(),
|
||||
SizedBox(height: 12.0.h()),
|
||||
_descriptionText(),
|
||||
SizedBox(height: 24.0.h()),
|
||||
_serviceDropDown(),
|
||||
SizedBox(height: 24.0.h()),
|
||||
_requirementsDropDown(),
|
||||
SizedBox(height: 24.0.h()),
|
||||
_backgroundDropDown(),
|
||||
// AI-NOTE (for PR reviewer): Mock dropdowns disabled (kept for future).
|
||||
// _serviceDropDown(),
|
||||
// SizedBox(height: 24.0.h()),
|
||||
// _requirementsDropDown(),
|
||||
// SizedBox(height: 24.0.h()),
|
||||
// _backgroundDropDown(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _serviceDropDown() =>
|
||||
const DetailDropDown(title: 'Servive/Product', items: []);
|
||||
|
||||
Widget _backgroundDropDown() =>
|
||||
const DetailDropDown(title: 'Background', items: []);
|
||||
|
||||
Widget _requirementsDropDown() {
|
||||
return const DetailDropDown(
|
||||
title: 'Requirements (Summary)',
|
||||
items: [
|
||||
'Market consultation for selecting and procuring a Customer Data Platform (CDP) to unify student data from multiple sources and improve personalization and marketing.',
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _descriptionText() {
|
||||
return Text(
|
||||
detail.description ?? '',
|
||||
@@ -101,6 +94,26 @@ class TenderDetailHeader extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
// AI-NOTE (for PR reviewer): The mock widget builders below are intentionally
|
||||
// preserved as commented-out code. They produce static placeholder content
|
||||
// (not backend-driven) and will be reinstated once the API supplies the
|
||||
// corresponding fields. Do not flag them as dead code — keep as-is.
|
||||
/*
|
||||
Widget _serviceDropDown() =>
|
||||
const DetailDropDown(title: 'Servive/Product', items: []);
|
||||
|
||||
Widget _backgroundDropDown() =>
|
||||
const DetailDropDown(title: 'Background', items: []);
|
||||
|
||||
Widget _requirementsDropDown() {
|
||||
return const DetailDropDown(
|
||||
title: 'Requirements (Summary)',
|
||||
items: [
|
||||
'Market consultation for selecting and procuring a Customer Data Platform (CDP) to unify student data from multiple sources and improve personalization and marketing.',
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _keyRisksDropDown() {
|
||||
return const DetailDropDown(
|
||||
title: 'Key risks & dealbreakers',
|
||||
@@ -146,7 +159,7 @@ class TenderDetailHeader extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
'Difficulty 2/5',
|
||||
'Difficulty 2/5',
|
||||
style: TextStyle(
|
||||
color: AppColors.blue10,
|
||||
fontSize: 12.0.sp(),
|
||||
@@ -167,7 +180,7 @@ class TenderDetailHeader extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
'Project ID 6243372025NLD',
|
||||
'Project ID 6243372025NLD',
|
||||
style: TextStyle(
|
||||
color: AppColors.blue10,
|
||||
fontSize: 12.0.sp(),
|
||||
@@ -176,6 +189,7 @@ class TenderDetailHeader extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
Widget _locationBudgetRow() {
|
||||
return Row(
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tm_app/core/theme/colors.dart';
|
||||
import 'package:tm_app/core/utils/date_utils.dart';
|
||||
import 'package:tm_app/core/utils/price_extension.dart';
|
||||
import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/data/services/model/tender_data/tender_data.dart';
|
||||
import 'package:tm_app/views/detail/strings/tender_details_strings.dart';
|
||||
import 'package:tm_app/views/detail/widgets/deadline_item.dart';
|
||||
import 'package:tm_app/views/detail/widgets/info_item.dart';
|
||||
|
||||
// AI-NOTE (for PR reviewer): This widget was rewritten to render ONLY the
|
||||
// backend-driven fields requested for the tender-details page (notice type,
|
||||
// form type, languages, issue/publication dates, procedure, value, duration,
|
||||
// deadlines, buyer org/address, lots, status, ids). Design is unchanged — it
|
||||
// still uses InfoItem/DeadlineItem. The _infoItem() helper returns an empty
|
||||
// list when a value is null/blank so empty fields don't render as blank rows
|
||||
// (this is why each entry is spread with `...`). The old hard-coded
|
||||
// "Reference Number" row was dropped because it isn't in the requested set.
|
||||
class TenderDetailInfoSection extends StatelessWidget {
|
||||
final bool isScreenBig;
|
||||
final TenderData detail;
|
||||
@@ -17,24 +28,114 @@ class TenderDetailInfoSection extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final buyer = detail.buyerOrganization;
|
||||
final address = buyer?.address;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
DeadlineItem(detail: detail, isScreenBig: isScreenBig),
|
||||
InfoItem(
|
||||
title: TenderDetailsStrings.tenderClientLabel,
|
||||
value: detail.buyerOrganization!.name ?? '',
|
||||
..._infoItem(TenderDetailsStrings.noticeTypeCode, detail.noticeTypeCode),
|
||||
..._infoItem(TenderDetailsStrings.formType, detail.formType),
|
||||
..._infoItem(
|
||||
TenderDetailsStrings.noticeLanguageCode,
|
||||
detail.noticeLanguageCode,
|
||||
),
|
||||
InfoItem(
|
||||
title: TenderDetailsStrings.estimatedValue,
|
||||
value:
|
||||
'${detail.estimatedValue?.formattedPrice} ${detail.currency ?? ''}',
|
||||
..._infoItem(
|
||||
TenderDetailsStrings.issueDate,
|
||||
_date(detail.issueDate),
|
||||
),
|
||||
InfoItem(
|
||||
title: TenderDetailsStrings.tenderReferenceNumberLabel,
|
||||
value: detail.noticePublicationId ?? '',
|
||||
..._infoItem(
|
||||
TenderDetailsStrings.issueTime,
|
||||
_dateTime(detail.issueTime),
|
||||
),
|
||||
..._infoItem(TenderDetailsStrings.procedureCode, detail.procedureCode),
|
||||
..._infoItem(
|
||||
TenderDetailsStrings.estimatedValue,
|
||||
detail.estimatedValue == null
|
||||
? null
|
||||
: '${detail.estimatedValue?.formattedPrice} ${detail.currency ?? ''}',
|
||||
),
|
||||
..._infoItem(TenderDetailsStrings.durationLabel, _duration()),
|
||||
..._infoItem(
|
||||
TenderDetailsStrings.publicationDate,
|
||||
_date(detail.publicationDate),
|
||||
),
|
||||
..._infoItem(
|
||||
TenderDetailsStrings.tenderDeadlineDate,
|
||||
_date(detail.tenderDeadline),
|
||||
),
|
||||
..._infoItem(TenderDetailsStrings.countryCode, detail.countryCode),
|
||||
..._infoItem(TenderDetailsStrings.buyerName, buyer?.name),
|
||||
..._infoItem(TenderDetailsStrings.companyId, buyer?.companyId),
|
||||
..._infoItem(TenderDetailsStrings.buyerCity, address?.cityName),
|
||||
..._infoItem(TenderDetailsStrings.buyerCountry, address?.countryCode),
|
||||
..._infoItem(
|
||||
TenderDetailsStrings.officialLanguages,
|
||||
(detail.officialLanguages == null ||
|
||||
detail.officialLanguages!.isEmpty)
|
||||
? null
|
||||
: detail.officialLanguages!.join(', '),
|
||||
),
|
||||
..._infoItem(TenderDetailsStrings.status, detail.status),
|
||||
..._infoItem(TenderDetailsStrings.tenderId, detail.tenderId),
|
||||
..._lotsSection(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns an [InfoItem] only when [value] has content, so empty fields are
|
||||
/// not rendered as blank rows.
|
||||
List<Widget> _infoItem(String title, String? value) {
|
||||
if (value == null || value.trim().isEmpty) {
|
||||
return const [];
|
||||
}
|
||||
return [InfoItem(title: title, value: value)];
|
||||
}
|
||||
|
||||
List<Widget> _lotsSection() {
|
||||
final lots = detail.lots;
|
||||
if (lots == null || lots.isEmpty) {
|
||||
return const [];
|
||||
}
|
||||
|
||||
return [
|
||||
SizedBox(height: 8.0.h()),
|
||||
Text(
|
||||
TenderDetailsStrings.lots,
|
||||
style: TextStyle(
|
||||
color: AppColors.grey80,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16.0.sp(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.0.h()),
|
||||
for (final lot in lots) ...[
|
||||
..._infoItem(TenderDetailsStrings.lotId, lot.lotId),
|
||||
..._infoItem('Title', lot.title),
|
||||
..._infoItem('Description', lot.description),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
String? _duration() {
|
||||
final duration = detail.duration?.trim() ?? '';
|
||||
final unit = detail.durationUnit?.trim() ?? '';
|
||||
final combined = '$duration $unit'.trim();
|
||||
return combined.isEmpty ? null : combined;
|
||||
}
|
||||
|
||||
String? _date(int? unix) {
|
||||
if (unix == null) {
|
||||
return null;
|
||||
}
|
||||
return timeConvertor(unix);
|
||||
}
|
||||
|
||||
String? _dateTime(int? unix) {
|
||||
if (unix == null) {
|
||||
return null;
|
||||
}
|
||||
return timeConvertor(unix, hasTime: true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,25 +87,30 @@ class DesktopNavigationWidget extends StatelessWidget {
|
||||
iconPath: AssetsManager.tenders,
|
||||
activeIconPath: AssetsManager.tendersActive,
|
||||
),
|
||||
const SizedBox(width: 24),
|
||||
_navigationItem(
|
||||
context: context,
|
||||
text: TendersStrings.board,
|
||||
isActive: currentIndex == 2,
|
||||
onTap: () {
|
||||
if (currentIndex == 2) {
|
||||
return;
|
||||
} else {
|
||||
Router.neglect(
|
||||
context,
|
||||
() => const BoardRouteData().go(context),
|
||||
);
|
||||
// context.read<TendersViewModel>().getTenders();
|
||||
}
|
||||
},
|
||||
iconPath: AssetsManager.board,
|
||||
activeIconPath: AssetsManager.boardActive,
|
||||
),
|
||||
// AI-NOTE (for PR reviewer): Board tab disabled (commented, not
|
||||
// removed) to hide the Board page from desktop navigation per request.
|
||||
// The Board route/page itself is left intact; re-enable this nav item
|
||||
// to bring the tab back. Note the tab indices of later items are
|
||||
// unchanged because this block is fully commented out.
|
||||
// const SizedBox(width: 24),
|
||||
// _navigationItem(
|
||||
// context: context,
|
||||
// text: TendersStrings.board,
|
||||
// isActive: currentIndex == 2,
|
||||
// onTap: () {
|
||||
// if (currentIndex == 2) {
|
||||
// return;
|
||||
// } else {
|
||||
// Router.neglect(
|
||||
// context,
|
||||
// () => const BoardRouteData().go(context),
|
||||
// );
|
||||
// // context.read<TendersViewModel>().getTenders();
|
||||
// }
|
||||
// },
|
||||
// iconPath: AssetsManager.board,
|
||||
// activeIconPath: AssetsManager.boardActive,
|
||||
// ),
|
||||
const SizedBox(width: 24),
|
||||
_navigationItem(
|
||||
context: context,
|
||||
|
||||
@@ -13,7 +13,6 @@ import 'package:tm_app/views/tenders/strings/tenders_strings.dart';
|
||||
import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart';
|
||||
import 'package:tm_app/views/tenders/widgets/tenders_filter_dialog.dart';
|
||||
import 'package:tm_app/views/tenders/widgets/tenders_sort_dialog.dart';
|
||||
import 'package:tm_app/views/tenders/widgets/windowed_pagination.dart';
|
||||
|
||||
import '../../../core/constants/common_strings.dart';
|
||||
import '../../../core/utils/app_toast.dart';
|
||||
@@ -78,13 +77,9 @@ class _DesktopTendersPageState extends State<DesktopTendersPage> {
|
||||
return const Center(child: Text(CommonStrings.noData));
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
return Center(
|
||||
child: SizedBox(
|
||||
width: 740,
|
||||
height: 800,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 4.0.h()),
|
||||
child: MainTendersSlider(
|
||||
@@ -93,17 +88,6 @@ class _DesktopTendersPageState extends State<DesktopTendersPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 740,
|
||||
child: WindowedPagination(
|
||||
currentPage: vm.currentPageIndex,
|
||||
totalPages: vm.totalPages,
|
||||
onPageChanged: vm.handlePaginationChange,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -9,7 +9,6 @@ import '../../../core/utils/app_toast.dart';
|
||||
import '../../shared/tender_app_bar.dart';
|
||||
import '../strings/tenders_strings.dart';
|
||||
import '../widgets/main_tenders_slider.dart';
|
||||
import '../widgets/windowed_pagination.dart';
|
||||
|
||||
class MobileTendersPage extends StatefulWidget {
|
||||
const MobileTendersPage({super.key});
|
||||
@@ -62,29 +61,13 @@ class _MobileTendersPageState extends State<MobileTendersPage> {
|
||||
return const Center(child: Text(CommonStrings.noData));
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
return SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 18.0.h()),
|
||||
child: MainTendersSlider(
|
||||
key: ValueKey(
|
||||
'tenders-slider-${viewModel.currentPageIndex}',
|
||||
),
|
||||
tenders:
|
||||
viewModel.tendersResponse?.data?.tenders ?? [],
|
||||
tenders: viewModel.tendersResponse?.data?.tenders ?? [],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
WindowedPagination(
|
||||
currentPage: viewModel.currentPageIndex,
|
||||
totalPages: viewModel.totalPages,
|
||||
onPageChanged: viewModel.handlePaginationChange,
|
||||
compact: true,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:tm_app/core/utils/size_config.dart';
|
||||
import 'package:tm_app/view_models/tenders_view_model.dart';
|
||||
import 'package:tm_app/views/shared/tablet_navigation_widget.dart';
|
||||
import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart';
|
||||
import 'package:tm_app/views/tenders/widgets/windowed_pagination.dart';
|
||||
|
||||
import '../../../core/constants/common_strings.dart';
|
||||
import '../../shared/tender_app_bar.dart';
|
||||
@@ -54,30 +53,16 @@ class _TabletTendersPageState extends State<TabletTendersPage> {
|
||||
viewModel.isLoading == false) {
|
||||
return const Center(child: Text(CommonStrings.noData));
|
||||
}
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
return SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: EdgeInsetsDirectional.only(
|
||||
end: 24.0.w(),
|
||||
top: 128.0.h(),
|
||||
),
|
||||
child: MainTendersSlider(
|
||||
key: ValueKey(
|
||||
'tenders-slider-${viewModel.currentPageIndex}',
|
||||
),
|
||||
tenders: viewModel.tendersResponse?.data?.tenders ?? [],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
WindowedPagination(
|
||||
currentPage: viewModel.currentPageIndex,
|
||||
totalPages: viewModel.totalPages,
|
||||
onPageChanged: viewModel.handlePaginationChange,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -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 +
|
||||
|
||||
@@ -8,7 +8,11 @@ import '../../../core/constants/assets.dart';
|
||||
import '../../../core/theme/colors.dart';
|
||||
import '../../../core/utils/date_utils.dart';
|
||||
import '../../../core/utils/size_config.dart';
|
||||
import '../../detail/strings/tender_details_strings.dart';
|
||||
// AI-NOTE (for PR reviewer): Import kept (commented) because the match-percentage
|
||||
// section it feeds (TenderDetailsStrings.tenderMatchProfile) is disabled, not
|
||||
// removed. Re-enable alongside _matchPercentage()/_progressBar() below when the
|
||||
// "match with profile" value comes from the backend.
|
||||
// import '../../detail/strings/tender_details_strings.dart';
|
||||
import '../../shared/flag.dart';
|
||||
import '../strings/tenders_strings.dart';
|
||||
import 'tender_action_buttons_row.dart';
|
||||
@@ -83,13 +87,17 @@ class TenderCard extends StatelessWidget {
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Match percentage
|
||||
_matchPercentage(),
|
||||
SizedBox(height: isDesktop ? 4.0.h() : 8.0.h()),
|
||||
|
||||
// Progress bar
|
||||
_progressBar(),
|
||||
SizedBox(height: isDesktop ? 8.0.h() : 16.0.h()),
|
||||
// AI-NOTE (for PR reviewer): The "Match with your profile"
|
||||
// label, the 45% value and the progress bar are disabled on
|
||||
// purpose (kept for future use). They show a hard-coded 45%,
|
||||
// not a backend value, so they are commented out, not deleted.
|
||||
// // Match percentage
|
||||
// _matchPercentage(),
|
||||
// SizedBox(height: isDesktop ? 4.0.h() : 8.0.h()),
|
||||
//
|
||||
// // Progress bar
|
||||
// _progressBar(),
|
||||
// SizedBox(height: isDesktop ? 8.0.h() : 16.0.h()),
|
||||
|
||||
// Location and apply button
|
||||
Row(
|
||||
@@ -243,6 +251,11 @@ class TenderCard extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
// AI-NOTE (for PR reviewer): _matchPercentage() and _progressBar() are
|
||||
// preserved as commented-out code. Both render a hard-coded 45% placeholder
|
||||
// (no backend source yet), so they are disabled rather than removed. Keep them
|
||||
// for when the profile-match score becomes available from the API.
|
||||
/*
|
||||
Widget _matchPercentage() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@@ -287,6 +300,7 @@ class TenderCard extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
Widget _locationInfo() {
|
||||
return Expanded(
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tm_app/core/theme/colors.dart';
|
||||
|
||||
/// A windowed numbered pagination widget that mirrors the Next.js
|
||||
/// implementation: ±10 page-button window around the current page,
|
||||
/// 1-based labels, prev/next chevrons.
|
||||
class WindowedPagination extends StatelessWidget {
|
||||
const WindowedPagination({
|
||||
super.key,
|
||||
required this.currentPage,
|
||||
required this.totalPages,
|
||||
required this.onPageChanged,
|
||||
this.maxPageJump = 10,
|
||||
this.compact = false,
|
||||
});
|
||||
|
||||
/// 0-based absolute current page index.
|
||||
final int currentPage;
|
||||
|
||||
/// Total number of pages (1-based count).
|
||||
final int totalPages;
|
||||
|
||||
/// Called with the 0-based target page index.
|
||||
final ValueChanged<int> onPageChanged;
|
||||
|
||||
/// Half-width of the page-button window (web uses 10).
|
||||
final int maxPageJump;
|
||||
|
||||
/// If true, renders smaller buttons (for mobile).
|
||||
final bool compact;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (totalPages <= 1) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final clampedCurrent = currentPage.clamp(0, totalPages - 1);
|
||||
final windowStart = (clampedCurrent - maxPageJump).clamp(0, totalPages - 1);
|
||||
final windowEnd = (clampedCurrent + maxPageJump).clamp(0, totalPages - 1);
|
||||
|
||||
final buttons = <Widget>[];
|
||||
|
||||
buttons.add(
|
||||
_NavButton(
|
||||
icon: Icons.chevron_left,
|
||||
enabled: clampedCurrent > 0,
|
||||
compact: compact,
|
||||
onTap: () => onPageChanged(clampedCurrent - 1),
|
||||
),
|
||||
);
|
||||
|
||||
if (windowStart > 0) {
|
||||
buttons.add(_buildPageButton(0, clampedCurrent));
|
||||
if (windowStart > 1) {
|
||||
buttons.add(const _Ellipsis());
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = windowStart; i <= windowEnd; i++) {
|
||||
buttons.add(_buildPageButton(i, clampedCurrent));
|
||||
}
|
||||
|
||||
if (windowEnd < totalPages - 1) {
|
||||
if (windowEnd < totalPages - 2) {
|
||||
buttons.add(const _Ellipsis());
|
||||
}
|
||||
buttons.add(_buildPageButton(totalPages - 1, clampedCurrent));
|
||||
}
|
||||
|
||||
buttons.add(
|
||||
_NavButton(
|
||||
icon: Icons.chevron_right,
|
||||
enabled: clampedCurrent < totalPages - 1,
|
||||
compact: compact,
|
||||
onTap: () => onPageChanged(clampedCurrent + 1),
|
||||
),
|
||||
);
|
||||
|
||||
final gap = compact ? 4.0 : 6.0;
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: compact ? 8 : 12),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(minWidth: constraints.maxWidth),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: _withSpacing(buttons, gap),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPageButton(int pageIndex, int currentPageIndex) {
|
||||
final isActive = pageIndex == currentPageIndex;
|
||||
return _PageButton(
|
||||
label: '${pageIndex + 1}',
|
||||
isActive: isActive,
|
||||
compact: compact,
|
||||
onTap: isActive ? null : () => onPageChanged(pageIndex),
|
||||
);
|
||||
}
|
||||
|
||||
static List<Widget> _withSpacing(List<Widget> items, double gap) {
|
||||
final result = <Widget>[];
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
result.add(items[i]);
|
||||
if (i != items.length - 1) {
|
||||
result.add(SizedBox(width: gap));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
class _PageButton extends StatelessWidget {
|
||||
const _PageButton({
|
||||
required this.label,
|
||||
required this.isActive,
|
||||
required this.compact,
|
||||
this.onTap,
|
||||
});
|
||||
|
||||
final String label;
|
||||
final bool isActive;
|
||||
final bool compact;
|
||||
final VoidCallback? onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final size = compact ? 32.0 : 38.0;
|
||||
return SizedBox(
|
||||
width: size,
|
||||
height: size,
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
gradient: isActive
|
||||
? const LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [AppColors.mainBlue, AppColors.primaryColor],
|
||||
)
|
||||
: null,
|
||||
color: isActive ? null : AppColors.grey0,
|
||||
border: Border.all(
|
||||
color: isActive ? Colors.transparent : AppColors.grey30,
|
||||
width: 1,
|
||||
),
|
||||
boxShadow: isActive
|
||||
? [
|
||||
BoxShadow(
|
||||
color: AppColors.mainBlue.withValues(alpha: 0.25),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
]
|
||||
: null,
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: compact ? 12 : 13,
|
||||
fontWeight: isActive ? FontWeight.w600 : FontWeight.w500,
|
||||
color: isActive ? Colors.white : AppColors.grey70,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _NavButton extends StatelessWidget {
|
||||
const _NavButton({
|
||||
required this.icon,
|
||||
required this.enabled,
|
||||
required this.compact,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
final IconData icon;
|
||||
final bool enabled;
|
||||
final bool compact;
|
||||
final VoidCallback onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final size = compact ? 32.0 : 38.0;
|
||||
return SizedBox(
|
||||
width: size,
|
||||
height: size,
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: enabled ? onTap : null,
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: AppColors.grey0,
|
||||
border: Border.all(
|
||||
color: enabled ? AppColors.grey30 : AppColors.grey20,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Icon(
|
||||
icon,
|
||||
size: compact ? 18 : 20,
|
||||
color: enabled ? AppColors.grey70 : AppColors.grey40,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _Ellipsis extends StatelessWidget {
|
||||
const _Ellipsis();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 2),
|
||||
child: Text(
|
||||
'…',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: AppColors.grey60,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,10 @@ void main() {
|
||||
expect(feedback.tender?.buyerOrganization?.name, 'Buyer Org');
|
||||
});
|
||||
|
||||
// AI-NOTE (for PR reviewer): These TenderData/Organization literals were
|
||||
// updated only to satisfy the new required fields added to those models
|
||||
// (notice_type_code, form_type, issue_date/time, lots, official_languages,
|
||||
// company_id, address). Test assertions/behavior are unchanged.
|
||||
test('toJson should return valid JSON map', () {
|
||||
final tender = const TenderData(
|
||||
success: true,
|
||||
@@ -58,6 +62,11 @@ void main() {
|
||||
id: 'TND123',
|
||||
tenderId: 'TND123',
|
||||
noticePublicationId: 'NP123',
|
||||
noticeTypeCode: 'cn-standard',
|
||||
formType: 'competition',
|
||||
noticeLanguageCode: 'ENG',
|
||||
issueDate: 1700000000,
|
||||
issueTime: 1700000000,
|
||||
publicationDate: 1700000000,
|
||||
title: 'Tender Title',
|
||||
description: 'Some description',
|
||||
@@ -74,7 +83,11 @@ void main() {
|
||||
durationUnit: 'month',
|
||||
buyerOrganization: Organization(
|
||||
name: 'Test Organization',
|
||||
companyId: 'ORG001',
|
||||
address: null,
|
||||
),
|
||||
lots: null,
|
||||
officialLanguages: null,
|
||||
status: 'active',
|
||||
);
|
||||
|
||||
@@ -114,6 +127,11 @@ void main() {
|
||||
id: 'TND001',
|
||||
tenderId: 'TND001',
|
||||
noticePublicationId: 'NP1',
|
||||
noticeTypeCode: 'cn-standard',
|
||||
formType: 'competition',
|
||||
noticeLanguageCode: 'ENG',
|
||||
issueDate: 1700000000,
|
||||
issueTime: 1700000000,
|
||||
publicationDate: 1700000000,
|
||||
title: 'Old Tender',
|
||||
description: 'Old desc',
|
||||
@@ -130,7 +148,11 @@ void main() {
|
||||
durationUnit: 'month',
|
||||
buyerOrganization: Organization(
|
||||
name: 'Old Org',
|
||||
companyId: 'ORG001',
|
||||
address: null,
|
||||
),
|
||||
lots: null,
|
||||
officialLanguages: null,
|
||||
status: 'inactive',
|
||||
),
|
||||
updatedAt: 1750000000,
|
||||
|
||||
Reference in New Issue
Block a user