diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index 7b4b3c7..1d269f8 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -25,7 +25,7 @@ android {
applicationId = "com.opplens.app"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
- minSdk = flutter.minSdkVersion
+ minSdk = 23
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
diff --git a/android/app/google-services.json b/android/app/google-services.json
index 03e737b..6766643 100644
--- a/android/app/google-services.json
+++ b/android/app/google-services.json
@@ -1,13 +1,13 @@
{
"project_info": {
- "project_number": "1071558853812",
- "project_id": "opplens",
- "storage_bucket": "opplens.firebasestorage.app"
+ "project_number": "6923326255",
+ "project_id": "opplens-270d1",
+ "storage_bucket": "opplens-270d1.firebasestorage.app"
},
"client": [
{
"client_info": {
- "mobilesdk_app_id": "1:1071558853812:android:7831119a56a99c5948c3e1",
+ "mobilesdk_app_id": "1:6923326255:android:6704c5b71e4451abed87da",
"android_client_info": {
"package_name": "com.opplens.app"
}
@@ -15,7 +15,7 @@
"oauth_client": [],
"api_key": [
{
- "current_key": "AIzaSyD5LaGXppjGEdTf-a0Ha25FX1p0v_h-c8A"
+ "current_key": "AIzaSyCqZ6B5iih0RdFj0lf5_erwbZvMyb7obEg"
}
],
"services": {
diff --git a/assets/icons/search_normal.svg b/assets/icons/search_normal.svg
new file mode 100644
index 0000000..ff9b6e2
--- /dev/null
+++ b/assets/icons/search_normal.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/sort.svg b/assets/icons/sort.svg
new file mode 100644
index 0000000..bf462ba
--- /dev/null
+++ b/assets/icons/sort.svg
@@ -0,0 +1,5 @@
+
diff --git a/lib/core/constants/assets.dart b/lib/core/constants/assets.dart
index 33252ae..8c821a0 100644
--- a/lib/core/constants/assets.dart
+++ b/lib/core/constants/assets.dart
@@ -40,6 +40,8 @@ class AssetsManager {
static const arrowLeftSmall = 'assets/icons/arrow-left-small.svg';
static const arrowRightSmall = 'assets/icons/arrow-right-small.svg';
static const tick = 'assets/icons/tick.svg';
+ static const normalSearch = 'assets/icons/search_normal.svg';
+ static const sort = 'assets/icons/sort.svg';
//home page
static const arrows = 'assets/icons/arrows.svg';
diff --git a/lib/data/services/model/tenders/tenders_data/tenders_data.dart b/lib/data/services/model/tenders/tenders_data/tenders_data.dart
index 9e046ea..f3f0082 100644
--- a/lib/data/services/model/tenders/tenders_data/tenders_data.dart
+++ b/lib/data/services/model/tenders/tenders_data/tenders_data.dart
@@ -12,7 +12,6 @@ part 'tenders_data.g.dart';
abstract class TendersData with _$TendersData {
const factory TendersData({
required List? tenders,
- required Meta? metadata,
}) = _TendersData;
factory TendersData.fromJson(Map json) =>
diff --git a/lib/data/services/model/tenders/tenders_data/tenders_data.freezed.dart b/lib/data/services/model/tenders/tenders_data/tenders_data.freezed.dart
index 77d49f3..eb48288 100644
--- a/lib/data/services/model/tenders/tenders_data/tenders_data.freezed.dart
+++ b/lib/data/services/model/tenders/tenders_data/tenders_data.freezed.dart
@@ -15,7 +15,7 @@ T _$identity(T value) => value;
/// @nodoc
mixin _$TendersData {
- List? get tenders; Meta? get metadata;
+ List? get tenders;
/// Create a copy of TendersData
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -28,16 +28,16 @@ $TendersDataCopyWith get copyWith => _$TendersDataCopyWithImpl Object.hash(runtimeType,const DeepCollectionEquality().hash(tenders),metadata);
+int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(tenders));
@override
String toString() {
- return 'TendersData(tenders: $tenders, metadata: $metadata)';
+ return 'TendersData(tenders: $tenders)';
}
@@ -48,11 +48,11 @@ abstract mixin class $TendersDataCopyWith<$Res> {
factory $TendersDataCopyWith(TendersData value, $Res Function(TendersData) _then) = _$TendersDataCopyWithImpl;
@useResult
$Res call({
- List? tenders, Meta? metadata
+ List? tenders
});
-$MetaCopyWith<$Res>? get metadata;
+
}
/// @nodoc
@@ -65,26 +65,13 @@ class _$TendersDataCopyWithImpl<$Res>
/// Create a copy of TendersData
/// with the given fields replaced by the non-null parameter values.
-@pragma('vm:prefer-inline') @override $Res call({Object? tenders = freezed,Object? metadata = freezed,}) {
+@pragma('vm:prefer-inline') @override $Res call({Object? tenders = freezed,}) {
return _then(_self.copyWith(
tenders: freezed == tenders ? _self.tenders : tenders // ignore: cast_nullable_to_non_nullable
-as List?,metadata: freezed == metadata ? _self.metadata : metadata // ignore: cast_nullable_to_non_nullable
-as Meta?,
+as List?,
));
}
-/// Create a copy of TendersData
-/// with the given fields replaced by the non-null parameter values.
-@override
-@pragma('vm:prefer-inline')
-$MetaCopyWith<$Res>? get metadata {
- if (_self.metadata == null) {
- return null;
- }
- return $MetaCopyWith<$Res>(_self.metadata!, (value) {
- return _then(_self.copyWith(metadata: value));
- });
-}
}
@@ -166,10 +153,10 @@ return $default(_that);case _:
/// }
/// ```
-@optionalTypeArgs TResult maybeWhen(TResult Function( List? tenders, Meta? metadata)? $default,{required TResult orElse(),}) {final _that = this;
+@optionalTypeArgs TResult maybeWhen(TResult Function( List? tenders)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _TendersData() when $default != null:
-return $default(_that.tenders,_that.metadata);case _:
+return $default(_that.tenders);case _:
return orElse();
}
@@ -187,10 +174,10 @@ return $default(_that.tenders,_that.metadata);case _:
/// }
/// ```
-@optionalTypeArgs TResult when(TResult Function( List? tenders, Meta? metadata) $default,) {final _that = this;
+@optionalTypeArgs TResult when(TResult Function( List? tenders) $default,) {final _that = this;
switch (_that) {
case _TendersData():
-return $default(_that.tenders,_that.metadata);case _:
+return $default(_that.tenders);case _:
throw StateError('Unexpected subclass');
}
@@ -207,10 +194,10 @@ return $default(_that.tenders,_that.metadata);case _:
/// }
/// ```
-@optionalTypeArgs TResult? whenOrNull(TResult? Function( List? tenders, Meta? metadata)? $default,) {final _that = this;
+@optionalTypeArgs TResult? whenOrNull(TResult? Function( List? tenders)? $default,) {final _that = this;
switch (_that) {
case _TendersData() when $default != null:
-return $default(_that.tenders,_that.metadata);case _:
+return $default(_that.tenders);case _:
return null;
}
@@ -222,7 +209,7 @@ return $default(_that.tenders,_that.metadata);case _:
@JsonSerializable()
class _TendersData implements TendersData {
- const _TendersData({required final List? tenders, required this.metadata}): _tenders = tenders;
+ const _TendersData({required final List? tenders}): _tenders = tenders;
factory _TendersData.fromJson(Map json) => _$TendersDataFromJson(json);
final List? _tenders;
@@ -234,7 +221,6 @@ class _TendersData implements TendersData {
return EqualUnmodifiableListView(value);
}
-@override final Meta? metadata;
/// Create a copy of TendersData
/// with the given fields replaced by the non-null parameter values.
@@ -249,16 +235,16 @@ Map toJson() {
@override
bool operator ==(Object other) {
- return identical(this, other) || (other.runtimeType == runtimeType&&other is _TendersData&&const DeepCollectionEquality().equals(other._tenders, _tenders)&&(identical(other.metadata, metadata) || other.metadata == metadata));
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is _TendersData&&const DeepCollectionEquality().equals(other._tenders, _tenders));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
-int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_tenders),metadata);
+int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_tenders));
@override
String toString() {
- return 'TendersData(tenders: $tenders, metadata: $metadata)';
+ return 'TendersData(tenders: $tenders)';
}
@@ -269,11 +255,11 @@ abstract mixin class _$TendersDataCopyWith<$Res> implements $TendersDataCopyWith
factory _$TendersDataCopyWith(_TendersData value, $Res Function(_TendersData) _then) = __$TendersDataCopyWithImpl;
@override @useResult
$Res call({
- List? tenders, Meta? metadata
+ List? tenders
});
-@override $MetaCopyWith<$Res>? get metadata;
+
}
/// @nodoc
@@ -286,27 +272,14 @@ class __$TendersDataCopyWithImpl<$Res>
/// Create a copy of TendersData
/// with the given fields replaced by the non-null parameter values.
-@override @pragma('vm:prefer-inline') $Res call({Object? tenders = freezed,Object? metadata = freezed,}) {
+@override @pragma('vm:prefer-inline') $Res call({Object? tenders = freezed,}) {
return _then(_TendersData(
tenders: freezed == tenders ? _self._tenders : tenders // ignore: cast_nullable_to_non_nullable
-as List?,metadata: freezed == metadata ? _self.metadata : metadata // ignore: cast_nullable_to_non_nullable
-as Meta?,
+as List?,
));
}
-/// Create a copy of TendersData
-/// with the given fields replaced by the non-null parameter values.
-@override
-@pragma('vm:prefer-inline')
-$MetaCopyWith<$Res>? get metadata {
- if (_self.metadata == null) {
- return null;
- }
- return $MetaCopyWith<$Res>(_self.metadata!, (value) {
- return _then(_self.copyWith(metadata: value));
- });
-}
}
// dart format on
diff --git a/lib/data/services/model/tenders/tenders_data/tenders_data.g.dart b/lib/data/services/model/tenders/tenders_data/tenders_data.g.dart
index 736dd48..4f8f13b 100644
--- a/lib/data/services/model/tenders/tenders_data/tenders_data.g.dart
+++ b/lib/data/services/model/tenders/tenders_data/tenders_data.g.dart
@@ -11,14 +11,7 @@ _TendersData _$TendersDataFromJson(Map json) => _TendersData(
(json['tenders'] as List?)
?.map((e) => TenderData.fromJson(e as Map))
.toList(),
- metadata:
- json['metadata'] == null
- ? null
- : Meta.fromJson(json['metadata'] as Map),
);
Map _$TendersDataToJson(_TendersData instance) =>
- {
- 'tenders': instance.tenders,
- 'metadata': instance.metadata,
- };
+ {'tenders': instance.tenders};
diff --git a/lib/data/services/model/tenders/tenders_response/tenders_response.dart b/lib/data/services/model/tenders/tenders_response/tenders_response.dart
index cd8a356..a3eaf95 100644
--- a/lib/data/services/model/tenders/tenders_response/tenders_response.dart
+++ b/lib/data/services/model/tenders/tenders_response/tenders_response.dart
@@ -1,6 +1,7 @@
// ignore_for_file: invalid_annotation_target
import 'package:freezed_annotation/freezed_annotation.dart';
+import 'package:tm_app/data/services/model/meta/meta.dart';
import '../../error/error_model.dart';
import '../tenders_data/tenders_data.dart';
@@ -15,6 +16,7 @@ abstract class TendersResponse with _$TendersResponse {
required ErrorModel? error,
required String? message,
required bool? success,
+ required Meta? meta,
}) = _TendersResponse;
factory TendersResponse.fromJson(Map json) =>
diff --git a/lib/data/services/model/tenders/tenders_response/tenders_response.freezed.dart b/lib/data/services/model/tenders/tenders_response/tenders_response.freezed.dart
index 0ad9ac4..3e67fbc 100644
--- a/lib/data/services/model/tenders/tenders_response/tenders_response.freezed.dart
+++ b/lib/data/services/model/tenders/tenders_response/tenders_response.freezed.dart
@@ -15,7 +15,7 @@ T _$identity(T value) => value;
/// @nodoc
mixin _$TendersResponse {
- TendersData? get data; ErrorModel? get error; String? get message; bool? get success;
+ TendersData? get data; ErrorModel? get error; String? get message; bool? get success; Meta? get meta;
/// Create a copy of TendersResponse
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -28,16 +28,16 @@ $TendersResponseCopyWith get copyWith => _$TendersResponseCopyW
@override
bool operator ==(Object other) {
- return identical(this, other) || (other.runtimeType == runtimeType&&other is TendersResponse&&(identical(other.data, data) || other.data == data)&&(identical(other.error, error) || other.error == error)&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success));
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is TendersResponse&&(identical(other.data, data) || other.data == data)&&(identical(other.error, error) || other.error == error)&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success)&&(identical(other.meta, meta) || other.meta == meta));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
-int get hashCode => Object.hash(runtimeType,data,error,message,success);
+int get hashCode => Object.hash(runtimeType,data,error,message,success,meta);
@override
String toString() {
- return 'TendersResponse(data: $data, error: $error, message: $message, success: $success)';
+ return 'TendersResponse(data: $data, error: $error, message: $message, success: $success, meta: $meta)';
}
@@ -48,11 +48,11 @@ abstract mixin class $TendersResponseCopyWith<$Res> {
factory $TendersResponseCopyWith(TendersResponse value, $Res Function(TendersResponse) _then) = _$TendersResponseCopyWithImpl;
@useResult
$Res call({
- TendersData? data, ErrorModel? error, String? message, bool? success
+ TendersData? data, ErrorModel? error, String? message, bool? success, Meta? meta
});
-$TendersDataCopyWith<$Res>? get data;$ErrorModelCopyWith<$Res>? get error;
+$TendersDataCopyWith<$Res>? get data;$ErrorModelCopyWith<$Res>? get error;$MetaCopyWith<$Res>? get meta;
}
/// @nodoc
@@ -65,13 +65,14 @@ class _$TendersResponseCopyWithImpl<$Res>
/// Create a copy of TendersResponse
/// with the given fields replaced by the non-null parameter values.
-@pragma('vm:prefer-inline') @override $Res call({Object? data = freezed,Object? error = freezed,Object? message = freezed,Object? success = freezed,}) {
+@pragma('vm:prefer-inline') @override $Res call({Object? data = freezed,Object? error = freezed,Object? message = freezed,Object? success = freezed,Object? meta = freezed,}) {
return _then(_self.copyWith(
data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
as TendersData?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
as ErrorModel?,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String?,success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
-as bool?,
+as bool?,meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
+as Meta?,
));
}
/// Create a copy of TendersResponse
@@ -98,6 +99,18 @@ $ErrorModelCopyWith<$Res>? get error {
return $ErrorModelCopyWith<$Res>(_self.error!, (value) {
return _then(_self.copyWith(error: value));
});
+}/// Create a copy of TendersResponse
+/// with the given fields replaced by the non-null parameter values.
+@override
+@pragma('vm:prefer-inline')
+$MetaCopyWith<$Res>? get meta {
+ if (_self.meta == null) {
+ return null;
+ }
+
+ return $MetaCopyWith<$Res>(_self.meta!, (value) {
+ return _then(_self.copyWith(meta: value));
+ });
}
}
@@ -180,10 +193,10 @@ return $default(_that);case _:
/// }
/// ```
-@optionalTypeArgs TResult maybeWhen(TResult Function( TendersData? data, ErrorModel? error, String? message, bool? success)? $default,{required TResult orElse(),}) {final _that = this;
+@optionalTypeArgs TResult maybeWhen(TResult Function( TendersData? data, ErrorModel? error, String? message, bool? success, Meta? meta)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _TendersResponse() when $default != null:
-return $default(_that.data,_that.error,_that.message,_that.success);case _:
+return $default(_that.data,_that.error,_that.message,_that.success,_that.meta);case _:
return orElse();
}
@@ -201,10 +214,10 @@ return $default(_that.data,_that.error,_that.message,_that.success);case _:
/// }
/// ```
-@optionalTypeArgs TResult when(TResult Function( TendersData? data, ErrorModel? error, String? message, bool? success) $default,) {final _that = this;
+@optionalTypeArgs TResult when(TResult Function( TendersData? data, ErrorModel? error, String? message, bool? success, Meta? meta) $default,) {final _that = this;
switch (_that) {
case _TendersResponse():
-return $default(_that.data,_that.error,_that.message,_that.success);case _:
+return $default(_that.data,_that.error,_that.message,_that.success,_that.meta);case _:
throw StateError('Unexpected subclass');
}
@@ -221,10 +234,10 @@ return $default(_that.data,_that.error,_that.message,_that.success);case _:
/// }
/// ```
-@optionalTypeArgs TResult? whenOrNull(TResult? Function( TendersData? data, ErrorModel? error, String? message, bool? success)? $default,) {final _that = this;
+@optionalTypeArgs TResult? whenOrNull(TResult? Function( TendersData? data, ErrorModel? error, String? message, bool? success, Meta? meta)? $default,) {final _that = this;
switch (_that) {
case _TendersResponse() when $default != null:
-return $default(_that.data,_that.error,_that.message,_that.success);case _:
+return $default(_that.data,_that.error,_that.message,_that.success,_that.meta);case _:
return null;
}
@@ -236,13 +249,14 @@ return $default(_that.data,_that.error,_that.message,_that.success);case _:
@JsonSerializable()
class _TendersResponse implements TendersResponse {
- const _TendersResponse({required this.data, required this.error, required this.message, required this.success});
+ const _TendersResponse({required this.data, required this.error, required this.message, required this.success, required this.meta});
factory _TendersResponse.fromJson(Map json) => _$TendersResponseFromJson(json);
@override final TendersData? data;
@override final ErrorModel? error;
@override final String? message;
@override final bool? success;
+@override final Meta? meta;
/// Create a copy of TendersResponse
/// with the given fields replaced by the non-null parameter values.
@@ -257,16 +271,16 @@ Map toJson() {
@override
bool operator ==(Object other) {
- return identical(this, other) || (other.runtimeType == runtimeType&&other is _TendersResponse&&(identical(other.data, data) || other.data == data)&&(identical(other.error, error) || other.error == error)&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success));
+ return identical(this, other) || (other.runtimeType == runtimeType&&other is _TendersResponse&&(identical(other.data, data) || other.data == data)&&(identical(other.error, error) || other.error == error)&&(identical(other.message, message) || other.message == message)&&(identical(other.success, success) || other.success == success)&&(identical(other.meta, meta) || other.meta == meta));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
-int get hashCode => Object.hash(runtimeType,data,error,message,success);
+int get hashCode => Object.hash(runtimeType,data,error,message,success,meta);
@override
String toString() {
- return 'TendersResponse(data: $data, error: $error, message: $message, success: $success)';
+ return 'TendersResponse(data: $data, error: $error, message: $message, success: $success, meta: $meta)';
}
@@ -277,11 +291,11 @@ abstract mixin class _$TendersResponseCopyWith<$Res> implements $TendersResponse
factory _$TendersResponseCopyWith(_TendersResponse value, $Res Function(_TendersResponse) _then) = __$TendersResponseCopyWithImpl;
@override @useResult
$Res call({
- TendersData? data, ErrorModel? error, String? message, bool? success
+ TendersData? data, ErrorModel? error, String? message, bool? success, Meta? meta
});
-@override $TendersDataCopyWith<$Res>? get data;@override $ErrorModelCopyWith<$Res>? get error;
+@override $TendersDataCopyWith<$Res>? get data;@override $ErrorModelCopyWith<$Res>? get error;@override $MetaCopyWith<$Res>? get meta;
}
/// @nodoc
@@ -294,13 +308,14 @@ class __$TendersResponseCopyWithImpl<$Res>
/// Create a copy of TendersResponse
/// with the given fields replaced by the non-null parameter values.
-@override @pragma('vm:prefer-inline') $Res call({Object? data = freezed,Object? error = freezed,Object? message = freezed,Object? success = freezed,}) {
+@override @pragma('vm:prefer-inline') $Res call({Object? data = freezed,Object? error = freezed,Object? message = freezed,Object? success = freezed,Object? meta = freezed,}) {
return _then(_TendersResponse(
data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
as TendersData?,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
as ErrorModel?,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String?,success: freezed == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
-as bool?,
+as bool?,meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
+as Meta?,
));
}
@@ -328,6 +343,18 @@ $ErrorModelCopyWith<$Res>? get error {
return $ErrorModelCopyWith<$Res>(_self.error!, (value) {
return _then(_self.copyWith(error: value));
});
+}/// Create a copy of TendersResponse
+/// with the given fields replaced by the non-null parameter values.
+@override
+@pragma('vm:prefer-inline')
+$MetaCopyWith<$Res>? get meta {
+ if (_self.meta == null) {
+ return null;
+ }
+
+ return $MetaCopyWith<$Res>(_self.meta!, (value) {
+ return _then(_self.copyWith(meta: value));
+ });
}
}
diff --git a/lib/data/services/model/tenders/tenders_response/tenders_response.g.dart b/lib/data/services/model/tenders/tenders_response/tenders_response.g.dart
index c5d3ccd..c023023 100644
--- a/lib/data/services/model/tenders/tenders_response/tenders_response.g.dart
+++ b/lib/data/services/model/tenders/tenders_response/tenders_response.g.dart
@@ -18,6 +18,10 @@ _TendersResponse _$TendersResponseFromJson(Map json) =>
: ErrorModel.fromJson(json['error'] as Map),
message: json['message'] as String?,
success: json['success'] as bool?,
+ meta:
+ json['meta'] == null
+ ? null
+ : Meta.fromJson(json['meta'] as Map),
);
Map _$TendersResponseToJson(_TendersResponse instance) =>
@@ -26,4 +30,5 @@ Map _$TendersResponseToJson(_TendersResponse instance) =>
'error': instance.error,
'message': instance.message,
'success': instance.success,
+ 'meta': instance.meta,
};
diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart
index 935ff91..06158cb 100644
--- a/lib/gen/assets.gen.dart
+++ b/lib/gen/assets.gen.dart
@@ -80,6 +80,9 @@ class $AssetsIconsGen {
/// File path: assets/icons/icon_contracts.svg
String get iconContracts => 'assets/icons/icon_contracts.svg';
+ /// File path: assets/icons/left-arrow.svg
+ String get leftArrow => 'assets/icons/left-arrow.svg';
+
/// File path: assets/icons/like.svg
String get like => 'assets/icons/like.svg';
@@ -113,9 +116,15 @@ class $AssetsIconsGen {
/// File path: assets/icons/profile-circle_active.svg
String get profileCircleActive => 'assets/icons/profile-circle_active.svg';
+ /// File path: assets/icons/search_normal.svg
+ String get searchNormal => 'assets/icons/search_normal.svg';
+
/// File path: assets/icons/shield.svg
String get shield => 'assets/icons/shield.svg';
+ /// File path: assets/icons/sort.svg
+ String get sort => 'assets/icons/sort.svg';
+
/// File path: assets/icons/sun.svg
String get sun => 'assets/icons/sun.svg';
@@ -180,6 +189,7 @@ class $AssetsIconsGen {
home,
homeActive,
iconContracts,
+ leftArrow,
like,
location,
logoBig,
@@ -191,7 +201,9 @@ class $AssetsIconsGen {
notifyIconActive,
profileCircle,
profileCircleActive,
+ searchNormal,
shield,
+ sort,
sun,
taskSquareActive,
taskSquare,
diff --git a/lib/main.dart b/lib/main.dart
index 52e7bb3..3380f0d 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -46,13 +46,13 @@ void main() async {
if (kIsWeb) {
await Firebase.initializeApp(
options: const FirebaseOptions(
- apiKey: 'AIzaSyAUQhM789-0qZIaIWtwTQXyz9gEtN-TnnU',
- authDomain: 'opplens.firebaseapp.com',
- appId: '1:1071558853812:web:d9ca896b088ee7da48c3e1',
- messagingSenderId: '1071558853812',
- projectId: 'opplens',
- storageBucket: 'opplens.firebasestorage.app',
- measurementId: 'G-GJGP9WB28B',
+ apiKey: 'AIzaSyCTjdsk2jE34IfnvSKP1JMTIf_Abd7tbt0',
+ authDomain: 'opplens-270d1.firebaseapp.com',
+ projectId: 'opplens-270d1',
+ storageBucket: 'opplens-270d1.firebasestorage.app',
+ messagingSenderId: '6923326255',
+ appId: '1:6923326255:web:c71763ece06aaaf3ed87da',
+ measurementId: 'G-M5HQR4YZVS',
),
);
final _firebaseMessaging = FirebaseMessaging.instance;
diff --git a/lib/view_models/tenders_view_model.dart b/lib/view_models/tenders_view_model.dart
index 8270978..9f4fc59 100644
--- a/lib/view_models/tenders_view_model.dart
+++ b/lib/view_models/tenders_view_model.dart
@@ -54,6 +54,8 @@ class TendersViewModel with ChangeNotifier {
int currentPage = 1;
int _currentOffset = 0;
+ int _totalPages = 0;
+ int get totalPages => _totalPages;
static const int _pageSize = 10;
bool _hasMoreData = true;
@@ -117,6 +119,14 @@ class TendersViewModel with ChangeNotifier {
getTenderFeedback(_tendersResponse!.data!.tenders!.first.id!);
getTenderApprovals(_tendersResponse!.data!.tenders!.first.id!);
}
+ if (_tendersResponse?.meta?.pages != null) {
+ _totalPages = _tendersResponse!.meta!.pages!;
+ print('Total pages: $_totalPages');
+ } else {
+ _totalPages = 1;
+ print('Total pages not available, fallback to 1');
+ }
+ notifyListeners();
break;
case Error():
_errorMessage = result.error.toString();
@@ -500,4 +510,35 @@ class TendersViewModel with ChangeNotifier {
_tenderApprovalErrorMessage = null;
notifyListeners();
}
+
+void jumpToPage(int page) async {
+ final meta = tendersResponse?.meta;
+ if (meta?.pages == null) {
+ return;
+ }
+ if (page < 1 || page > meta!.pages!) {
+ return;
+ }
+
+ currentPage = page;
+ _currentOffset = (page - 1) * _pageSize;
+
+ final result = await _tendersRepository.getTenders(
+ limit: _pageSize,
+ offset: _currentOffset,
+ );
+
+ switch (result) {
+ case Ok():
+ _tendersResponse = result.value;
+ break;
+ case Error():
+ _errorMessage = result.error.toString();
+ break;
+ }
+
+ notifyListeners();
+}
+
+
}
diff --git a/lib/views/shared/base_button.dart b/lib/views/shared/base_button.dart
index 6eee16d..09c471d 100644
--- a/lib/views/shared/base_button.dart
+++ b/lib/views/shared/base_button.dart
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
import '../../core/theme/colors.dart';
import '../../core/utils/size_config.dart';
@@ -16,6 +17,8 @@ class BaseButton extends StatelessWidget {
final double? elevation;
final double? width;
final bool isLoading;
+ final String? icon;
+ final Color? iconColor;
const BaseButton({
required this.isEnabled,
@@ -29,6 +32,8 @@ class BaseButton extends StatelessWidget {
this.elevation,
this.width,
this.isLoading = false,
+ this.icon,
+ this.iconColor,
super.key,
});
@@ -72,14 +77,38 @@ class BaseButton extends StatelessWidget {
),
),
),
- child: Text(
- text ?? LoginStrings.loginButton,
- style: TextStyle(
- fontSize: 16.0.sp(),
- fontWeight: FontWeight.bold,
- color: textColor ?? AppColors.white,
- ),
- ),
+ child:
+ icon != null
+ ? Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ SvgPicture.asset(
+ icon!,
+ colorFilter: ColorFilter.mode(
+ iconColor ?? AppColors.white,
+ BlendMode.srcIn,
+ ),
+ ),
+ SizedBox(width: 7.0.w()),
+ Text(
+ text ?? LoginStrings.loginButton,
+ style: TextStyle(
+ fontSize: 16.0.sp(),
+ fontWeight: FontWeight.bold,
+ color: textColor ?? AppColors.white,
+ ),
+ ),
+ ],
+ )
+ : Text(
+ text ?? LoginStrings.loginButton,
+ style: TextStyle(
+ fontSize: 16.0.sp(),
+ fontWeight: FontWeight.bold,
+ color: textColor ?? AppColors.white,
+ ),
+ ),
),
);
}
diff --git a/lib/views/tenders/pages/d_tenders_page.dart b/lib/views/tenders/pages/d_tenders_page.dart
index 5ec9d4e..0dff86c 100644
--- a/lib/views/tenders/pages/d_tenders_page.dart
+++ b/lib/views/tenders/pages/d_tenders_page.dart
@@ -1,9 +1,14 @@
import 'package:flutter/material.dart';
+import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
+import 'package:tm_app/core/constants/assets.dart';
import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/view_models/tenders_view_model.dart';
+import 'package:tm_app/views/shared/base_button.dart';
import 'package:tm_app/views/shared/desktop_navigation_widget.dart';
+import 'package:tm_app/views/shared/page_selection_dialog.dart';
+import 'package:tm_app/views/tenders/strings/tenders_strings.dart';
import 'package:tm_app/views/tenders/widgets/main_tenders_slider.dart';
import '../../../core/constants/common_strings.dart';
@@ -18,6 +23,7 @@ class DesktopTendersPage extends StatefulWidget {
class _DesktopTendersPageState extends State {
late final TendersViewModel viewModel;
+
@override
void initState() {
super.initState();
@@ -46,41 +52,49 @@ class _DesktopTendersPageState extends State {
backgroundColor: AppColors.backgroundColor,
body: Column(
children: [
- const DesktopNavigationWidget(
- currentIndex: 1, // Tenders index
- ),
+ const DesktopNavigationWidget(currentIndex: 1),
+ SizedBox(height: 48.0.h()),
+ const _SearchBox(),
+ const _ActionButtons(),
Expanded(
child: Consumer(
- builder: (context, viewModel, child) {
- if (viewModel.isLoading) {
- return const Expanded(
- child: Center(
- child: CircularProgressIndicator(
- color: AppColors.jellyBean,
- ),
- ),
+ builder: (context, vm, child) {
+ if (vm.isLoading) {
+ return const Center(
+ child: CircularProgressIndicator(color: AppColors.jellyBean),
);
}
- if (viewModel.errorMessage != null) {
- return Center(child: Text(viewModel.errorMessage!));
+ if (vm.errorMessage != null) {
+ return Center(child: Text(vm.errorMessage!));
}
- if ((viewModel.tendersResponse?.data?.tenders == null ||
- viewModel.tendersResponse!.data!.tenders!.isEmpty) &&
- viewModel.isLoading == false) {
+ final tenders = vm.tendersResponse?.data?.tenders ?? [];
+ if (tenders.isEmpty) {
return const Center(child: Text(CommonStrings.noData));
}
- return SingleChildScrollView(
- child: SizedBox(
- width: 740,
- height: 800,
- child: Padding(
- padding: EdgeInsets.symmetric(vertical: 24.0.h()),
- child: MainTendersSlider(
- tenders: viewModel.tendersResponse?.data?.tenders ?? [],
- isDesktop: true,
+
+ return Column(
+ children: [
+ Expanded(
+ child: SingleChildScrollView(
+ child: SizedBox(
+ width: 740,
+ height: 800,
+ child: Padding(
+ padding: EdgeInsets.symmetric(vertical: 4.0.h()),
+ child: MainTendersSlider(
+ tenders: tenders,
+ isDesktop: true,
+ ),
+ ),
+ ),
),
),
- ),
+ _DesktopPagination(
+ totalPages: vm.totalPages,
+ currentPage: vm.currentPage,
+ onPageSelected: vm.jumpToPage,
+ ),
+ ],
);
},
),
@@ -90,3 +104,174 @@ class _DesktopTendersPageState extends State {
);
}
}
+
+class _SearchBox extends StatelessWidget {
+ const _SearchBox();
+
+ @override
+ Widget build(BuildContext context) {
+ return SizedBox(
+ height: 48.0.h(),
+ width: 680,
+ child: TextField(
+ style: TextStyle(fontSize: 16.0.sp(), color: AppColors.grey0),
+ decoration: InputDecoration(
+ hintText: 'Search',
+ hintStyle: TextStyle(fontSize: 16.0.sp(), color: AppColors.grey60),
+ prefixIcon: Padding(
+ padding: EdgeInsets.all(12.0.w()),
+ child: SvgPicture.asset(
+ AssetsManager.normalSearch,
+ width: 24.0.w(),
+ height: 24.0.h(),
+ ),
+ ),
+ filled: true,
+ fillColor: AppColors.grey0,
+ contentPadding: EdgeInsets.symmetric(
+ horizontal: 12.0.w(),
+ vertical: 12.0.h(),
+ ),
+ border: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(12.0.w()),
+ borderSide: const BorderSide(color: AppColors.mainBlue, width: 1),
+ ),
+ enabledBorder: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(12.0.w()),
+ borderSide: BorderSide(color: AppColors.grey40, width: 1),
+ ),
+ focusedBorder: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(12.0.w()),
+ borderSide: const BorderSide(color: AppColors.grey, width: 1.5),
+ ),
+ ),
+ ),
+ );
+ }
+}
+
+class _ActionButtons extends StatelessWidget {
+ const _ActionButtons();
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ margin: EdgeInsets.only(top: 25.0.h()),
+ height: 40.0.h(),
+ width: 680,
+ child: Row(
+ children: [
+ BaseButton(
+ width: 178.0.w(),
+ isEnabled: true,
+ onPressed: () {},
+ text: 'Filter',
+ icon: AssetsManager.filter,
+ iconColor: AppColors.textBlue,
+ backgroundColor: AppColors.primary2,
+ textColor: AppColors.textBlue,
+ ),
+ SizedBox(width: 10.0.w()),
+ BaseButton(
+ width: 178.0.w(),
+ isEnabled: true,
+ onPressed: () {},
+ text: 'Sort',
+ icon: AssetsManager.sort,
+ iconColor: AppColors.textBlue,
+ backgroundColor: AppColors.primary2,
+ textColor: AppColors.textBlue,
+ ),
+ ],
+ ),
+ );
+ }
+}
+
+class _DesktopPagination extends StatelessWidget {
+ final int totalPages;
+ final int currentPage;
+ final ValueChanged onPageSelected;
+
+ const _DesktopPagination({
+ required this.totalPages,
+ required this.currentPage,
+ required this.onPageSelected,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return SizedBox(
+ width: 680,
+ child: Padding(
+ padding: EdgeInsets.symmetric(vertical: 12.0.h()),
+ child: Row(
+ children: [
+ const Spacer(),
+ Text(
+ TendersStrings.page,
+ style: TextStyle(
+ fontSize: 13.0.sp(),
+ fontWeight: FontWeight.w300,
+ color: AppColors.grey60,
+ ),
+ ),
+ SizedBox(width: 10.0.w()),
+ InkWell(
+ onTap: () async {
+ final selectedPage = await showDialog(
+ context: context,
+ builder: (context) =>
+ PageSelectionDialog(totalPages: totalPages),
+ );
+ if (selectedPage != null) {
+ onPageSelected(selectedPage);
+ }
+ },
+ child: Container(
+ decoration: BoxDecoration(
+ border: Border.all(color: AppColors.grey30, width: 1),
+ borderRadius: BorderRadius.circular(4),
+ ),
+ child: Row(
+ children: [
+ SizedBox(width: 5.0.w()),
+ Text(
+ '$currentPage',
+ style: TextStyle(
+ fontSize: 14.0.sp(),
+ fontWeight: FontWeight.w500,
+ color: AppColors.grey70,
+ ),
+ ),
+ SizedBox(width: 5.0.w()),
+ SvgPicture.asset(AssetsManager.arrowDownSmall),
+ SizedBox(width: 5.0.w()),
+ ],
+ ),
+ ),
+ ),
+ SizedBox(width: 5.0.w()),
+ Text(
+ TendersStrings.of,
+ style: TextStyle(
+ fontSize: 14.0.sp(),
+ fontWeight: FontWeight.w400,
+ color: AppColors.grey60,
+ ),
+ ),
+ SizedBox(width: 5.0.w()),
+ Text(
+ '$totalPages',
+ style: TextStyle(
+ fontSize: 13.0.sp(),
+ fontWeight: FontWeight.w400,
+ color: AppColors.grey60,
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/views/tenders/strings/tenders_strings.dart b/lib/views/tenders/strings/tenders_strings.dart
index b4cced5..259d4a8 100644
--- a/lib/views/tenders/strings/tenders_strings.dart
+++ b/lib/views/tenders/strings/tenders_strings.dart
@@ -10,4 +10,6 @@ class TendersStrings {
static const String tenderDeadlineLabel = 'Deadline';
static const String contracts = 'Contracts';
static const String notifications = 'Notifications';
+ static const String of= 'Of';
+ static const String page = 'Page';
}
diff --git a/lib/views/tenders/widgets/main_tenders_slider.dart b/lib/views/tenders/widgets/main_tenders_slider.dart
index 1ff7aae..294c709 100644
--- a/lib/views/tenders/widgets/main_tenders_slider.dart
+++ b/lib/views/tenders/widgets/main_tenders_slider.dart
@@ -15,6 +15,7 @@ class MainTendersSlider extends StatefulWidget {
super.key,
this.isDesktop = false,
});
+
final bool isDesktop;
final List tenders;
@@ -24,25 +25,54 @@ class MainTendersSlider extends StatefulWidget {
class _MainTendersSliderState extends State {
final PageController pageController = PageController(initialPage: 0);
-
int currentPage = 1;
+ ScrollController? _scrollController;
+
+ @override
+ void initState() {
+ super.initState();
+
+ if (widget.isDesktop) {
+ _scrollController = ScrollController();
+ _scrollController!.addListener(_onScroll);
+ }
+ }
+
+ void _onScroll() {
+ if (!widget.isDesktop) {
+ return;
+ }
+ final viewModel = context.read();
+ if (_scrollController!.position.pixels >=
+ _scrollController!.position.maxScrollExtent - 200 &&
+ viewModel.hasMoreData &&
+ !viewModel.isLoadingMore) {
+ viewModel.loadMoreTenders();
+ }
+ }
+
void _goToPreviousPage() {
if (currentPage == 1) {
return;
}
+ final targetIndex = currentPage - 2;
+ if (targetIndex < 0) {
+ return;
+ }
+
pageController.previousPage(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOutCubic,
);
+
setState(() {
currentPage = currentPage - 1;
});
- // Fetch feedback and approvals for the previous tender if not already loaded
final viewModel = context.read();
- final previousTenderId = widget.tenders[currentPage - 2].id!;
+ final previousTenderId = widget.tenders[targetIndex].id!;
if (!viewModel.hasFeedbackForTender(previousTenderId)) {
viewModel.getTenderFeedback(previousTenderId);
}
@@ -56,17 +86,22 @@ class _MainTendersSliderState extends State {
return;
}
+ final targetIndex = currentPage;
+ if (targetIndex >= widget.tenders.length) {
+ return;
+ }
+
pageController.nextPage(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOutCubic,
);
+
setState(() {
currentPage = currentPage + 1;
});
- // Fetch feedback and approvals for the next tender if not already loaded
final viewModel = context.read();
- final nextTenderId = widget.tenders[currentPage].id!;
+ final nextTenderId = widget.tenders[targetIndex].id!;
if (!viewModel.hasFeedbackForTender(nextTenderId)) {
viewModel.getTenderFeedback(nextTenderId);
}
@@ -78,16 +113,20 @@ class _MainTendersSliderState extends State {
@override
void dispose() {
pageController.dispose();
+ _scrollController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
- bool isLtr = Directionality.of(context) == TextDirection.ltr;
- return SingleChildScrollView(
- child: Stack(
- children: [_tendersPageView(), _nextPreviousArrows(isLtr: isLtr)],
- ),
+ final bool isLtr = Directionality.of(context) == TextDirection.ltr;
+
+ return widget.isDesktop ? _tendersListView() : _tendersSlider(isLtr);
+ }
+
+ Widget _tendersSlider(bool isLtr) {
+ return Stack(
+ children: [_tendersPageView(), _nextPreviousArrows(isLtr: isLtr)],
);
}
@@ -97,25 +136,21 @@ class _MainTendersSliderState extends State {
height: 722.0.h(),
child: PageView.builder(
controller: pageController,
- scrollDirection: Axis.horizontal,
itemCount: widget.tenders.length,
onPageChanged: (index) {
setState(() {
currentPage = index + 1;
});
- // Fetch feedback and approvals for the new tender if not already loaded
final viewModel = context.read();
- if (!viewModel.hasFeedbackForTender(widget.tenders[index].id!)) {
- viewModel.getTenderFeedback(widget.tenders[index].id!);
+ final id = widget.tenders[index].id!;
+ if (!viewModel.hasFeedbackForTender(id)) {
+ viewModel.getTenderFeedback(id);
}
- if (!viewModel.hasTenderApprovalForTender(
- widget.tenders[index].id!,
- )) {
- viewModel.getTenderApprovals(widget.tenders[index].id!);
+ if (!viewModel.hasTenderApprovalForTender(id)) {
+ viewModel.getTenderApprovals(id);
}
- // Check if we need to load more tenders (when user reaches near the end)
if (index >= widget.tenders.length - 1 &&
viewModel.hasMoreData &&
!viewModel.isLoadingMore) {
@@ -229,4 +264,38 @@ class _MainTendersSliderState extends State {
)
: SizedBox(width: 32.0.h(), height: 32.0.h());
}
+
+ Widget _tendersListView() {
+ final viewModel = context.watch();
+ return Column(
+ children: [
+ Expanded(
+ child: ListView.separated(
+ padding: EdgeInsets.all(16.0.h()),
+ itemCount:
+ widget.tenders.length +
+ (widget.isDesktop && viewModel.isLoadingMore ? 1 : 0),
+ separatorBuilder:
+ (_, __) => SizedBox(height: widget.isDesktop ? 0 : 16.0.h()),
+ itemBuilder: (context, index) {
+ if (index < widget.tenders.length) {
+ final tender = widget.tenders[index];
+ return TenderCard(tender: tender, isDesktop: widget.isDesktop);
+ } else {
+ return const Padding(
+ padding: EdgeInsets.all(16.0),
+ child: Center(
+ child: CircularProgressIndicator(
+ strokeWidth: 2.0,
+ color: AppColors.jellyBean,
+ ),
+ ),
+ );
+ }
+ },
+ ),
+ ),
+ ],
+ );
+ }
}
diff --git a/lib/views/tenders/widgets/tender_action_buttons_row.dart b/lib/views/tenders/widgets/tender_action_buttons_row.dart
index 02f56b9..f7ee40f 100644
--- a/lib/views/tenders/widgets/tender_action_buttons_row.dart
+++ b/lib/views/tenders/widgets/tender_action_buttons_row.dart
@@ -35,13 +35,13 @@ class TenderActionButtonsRow extends StatelessWidget {
// Dislike button
_dislikeButton(viewModel),
- SizedBox(width: 32.0.w()),
+ isDesktop ? Container() : SizedBox(width: 32.0.w()),
//reject button
- _rejectButton(viewModel),
- SizedBox(width: 32.0.w()),
+ isDesktop ? Container() : _rejectButton(viewModel),
+ isDesktop ? Container() : SizedBox(width: 32.0.w()),
//submit button
- _submitButton(viewModel, context),
- SizedBox(width: 32.0.w()),
+ isDesktop ? Container() : _submitButton(viewModel, context),
+ SizedBox(width: isDesktop ? 16.0.h() : 32.0.w()),
// Like button
_likeButton(viewModel),
],
diff --git a/lib/views/tenders/widgets/tender_card.dart b/lib/views/tenders/widgets/tender_card.dart
index 5c76bc1..b08424a 100644
--- a/lib/views/tenders/widgets/tender_card.dart
+++ b/lib/views/tenders/widgets/tender_card.dart
@@ -26,7 +26,7 @@ class TenderCard extends StatelessWidget {
Container(
width: double.infinity,
margin: EdgeInsets.symmetric(horizontal: 16.0.w()),
- height: 587.0.h(),
+ height: isDesktop ? 290.0.h() : 587.0.h(),
decoration: BoxDecoration(
color: AppColors.grey0,
borderRadius: BorderRadius.circular(12),
@@ -56,38 +56,41 @@ class TenderCard extends StatelessWidget {
// Deadline badge
_deadlineBadge(),
- SizedBox(height: 12.0.h()),
+ isDesktop ? Container() : SizedBox(height: 12.0.h()),
// Approval status badge
// _approvalStatusBadge(),
- SizedBox(height: 12.0.h()),
+ SizedBox(height: isDesktop ? 6.0.h() : 12.0.h()),
// Title
_tenderTitle(),
- SizedBox(height: 8.0.h()),
+ SizedBox(height: isDesktop ? 4.0.h() : 8.0.h()),
// Description
_tenderDescription(),
- SizedBox(height: 12.0.h()),
+ isDesktop ? Container() : SizedBox(height: 12.0.h()),
// Tender ID
- _idText(),
+ isDesktop ? Container() : _idText(),
],
),
),
const Spacer(),
// Bottom section with progress and actions
Padding(
- padding: EdgeInsets.all(16.0.w()),
+ padding: EdgeInsets.symmetric(
+ vertical: isDesktop ? 8.0.w() : 16.0.w(),
+ horizontal: 16.0.w(),
+ ),
child: Column(
children: [
// Match percentage
_matchPercentage(),
- SizedBox(height: 8.0.h()),
+ SizedBox(height: isDesktop ? 4.0.h() : 8.0.h()),
// Progress bar
_progressBar(),
- SizedBox(height: 16.0.h()),
+ SizedBox(height: isDesktop ? 8.0.h() : 16.0.h()),
// Location and apply button
Row(
@@ -105,7 +108,7 @@ class TenderCard extends StatelessWidget {
],
),
),
- SizedBox(height: 72.0.h()),
+ SizedBox(height: isDesktop ? 20.0.h() : 72.0.h()),
if (!isDesktop) TenderActionButtonsRow(tender: tender),
],
);
@@ -158,10 +161,11 @@ class TenderCard extends StatelessWidget {
Widget _tenderTitle() {
return Text(
tender.title ?? '',
+ maxLines: isDesktop ? 2 : 4,
style: TextStyle(
color: AppColors.grey80,
fontSize: 16.0.sp(),
- fontWeight: FontWeight.w600,
+ fontWeight: isDesktop ? FontWeight.w500 : FontWeight.w600,
),
);
}
@@ -169,11 +173,11 @@ class TenderCard extends StatelessWidget {
Widget _tenderDescription() {
return Text(
tender.description ?? '',
- maxLines: 4,
+ maxLines: isDesktop ? 2 : 4,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: AppColors.grey70,
- fontSize: 16.0.sp(),
+ fontSize: isDesktop ? 14.0.sp() : 16.0.sp(),
fontWeight: FontWeight.w400,
height: 1.5,
),
@@ -199,15 +203,15 @@ class TenderCard extends StatelessWidget {
TenderDetailsStrings.tenderMatchProfile,
style: TextStyle(
color: AppColors.grey80,
- fontSize: 14.0.sp(),
- fontWeight: FontWeight.w500,
+ fontSize: isDesktop ? 12.0.sp() : 14.0.sp(),
+ fontWeight: isDesktop ? FontWeight.w400 : FontWeight.w500,
),
),
Text(
'${45}%',
style: TextStyle(
color: AppColors.secondaryTextColor,
- fontSize: 16.0.sp(),
+ fontSize: isDesktop ? 12.0.sp() : 16.0.sp(),
fontWeight: FontWeight.w600,
),
),
diff --git a/web/firebase-messaging-sw.js b/web/firebase-messaging-sw.js
index 4630252..730ae3d 100644
--- a/web/firebase-messaging-sw.js
+++ b/web/firebase-messaging-sw.js
@@ -2,13 +2,13 @@ importScripts("https://www.gstatic.com/firebasejs/9.22.2/firebase-app-compat.js"
importScripts("https://www.gstatic.com/firebasejs/9.22.2/firebase-messaging-compat.js");
firebase.initializeApp({
- apiKey: 'AIzaSyAUQhM789-0qZIaIWtwTQXyz9gEtN-TnnU',
- authDomain: 'opplens.firebaseapp.com',
- appId: '1:1071558853812:web:d9ca896b088ee7da48c3e1',
- messagingSenderId: '1071558853812',
- projectId: 'opplens',
- storageBucket: 'opplens.firebasestorage.app',
- measurementId: 'G-GJGP9WB28B',
+ apiKey: "AIzaSyCTjdsk2jE34IfnvSKP1JMTIf_Abd7tbt0",
+ authDomain: "opplens-270d1.firebaseapp.com",
+ projectId: "opplens-270d1",
+ storageBucket: "opplens-270d1.firebasestorage.app",
+ messagingSenderId: "6923326255",
+ appId: "1:6923326255:web:c71763ece06aaaf3ed87da",
+ measurementId: "G-M5HQR4YZVS"
});
const messaging = firebase.messaging();