diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index e6c0a2b..0a911b6 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
+ android:value="45fe500d-b549-4444-9e4b-3b2acd78ee2c" />
> getClientFines() async {
+ try {
+ final response = await _dio.get(
+ "$baseUrl/scooterorder/fines/client",
+ options: await _getAuthOptions(),
+ );
+
+ if (response.statusCode == 200 && response.data is Map) {
+ final List dataList = response.data['data'] ?? [];
+ return dataList.map((json) => Fine.fromJson(json)).toList();
+ }
+ return [];
+ } on DioException catch (e) {
+ _handleDioError(e);
+ return [];
+ }
+ }
+
/// GET /scooterorder/{id}/fine
Future getFineDetails(int orderId) async {
try {
final response = await _dio.get(
- "$baseUrl/scooterorder/$orderId/fine",
+ "$baseUrl/scooterorder/fines/client/$orderId",
options: await _getAuthOptions(),
);
@@ -953,7 +972,8 @@ class ApiService {
}
}
- /// PUT /scooterorder/{id}/fine
+ /// PUT /scooterorder/fines/client/{id}
+ /// {id} — это id штрафа (Fine.id), а не id заказа (Fine.orderId)
Future payFine({
required int orderId,
int? cardId,
@@ -961,10 +981,10 @@ class ApiService {
}) async {
try {
await _dio.put(
- "$baseUrl/scooterorder/$orderId/fine",
+ "$baseUrl/scooterorder/fines/client/$orderId",
data: {
- if (cardId != null) 'cardId': cardId,
- 'isBalance': isBalance,
+ "cardId": cardId ?? 0,
+ "isBalance": isBalance,
},
options: await _getAuthOptions(),
);
diff --git a/lib/data/repositories/scooter_repository_impl.dart b/lib/data/repositories/scooter_repository_impl.dart
index 0655491..8907467 100644
--- a/lib/data/repositories/scooter_repository_impl.dart
+++ b/lib/data/repositories/scooter_repository_impl.dart
@@ -449,6 +449,24 @@ class ScooterRepositoryImpl extends ScooterRepository {
return result;
}
+ @override
+ Future>> getClientFines() async {
+ late final Result> result;
+ try {
+ final fines = await _apiService.getClientFines();
+ result = Success(fines);
+ } on AuthException catch (e) {
+ result = Failure(AuthFailure(e.attemptsLeft));
+ } on UnauthorizedException catch (e) {
+ result = Failure(AuthFailure(0, message: e.toString()));
+ } on AuthBlockException catch (e) {
+ result = Failure(AuthBlockFailure(e.toString()));
+ } catch (e) {
+ result = Failure(UnknownFailure("Неизвестная ошибка"));
+ }
+ return result;
+ }
+
@override
Future> payFine({
required int orderId,
diff --git a/lib/di/service_locator.dart b/lib/di/service_locator.dart
index 85b15d4..3b61f41 100644
--- a/lib/di/service_locator.dart
+++ b/lib/di/service_locator.dart
@@ -94,14 +94,18 @@ import '../domain/service/device_info_service.dart';
import '../domain/usecase/activate_subscription_usecase.dart';
import '../domain/usecase/apply_promo_code_usecase.dart';
import '../domain/usecase/get_client_subscriptions_usecase.dart';
+import '../domain/usecase/get_fine_details_usecase.dart';
+import '../domain/usecase/get_fines_usecase.dart';
import '../domain/usecase/get_news_by_id_usecase.dart';
import '../domain/usecase/get_notifications_usecase.dart';
import '../domain/usecase/get_scooter_by_title_usecase.dart';
import '../domain/usecase/get_scooter_order_history_usecase.dart';
+import '../domain/usecase/pay_fine_usecase.dart';
import '../domain/usecase/remove_payment_card_usecase.dart';
import '../domain/usecase/set_main_payment_card_usecase.dart';
import '../presentation/viewmodel/auth_bloc.dart';
import '../presentation/viewmodel/edit_profile_bloc.dart';
+import '../presentation/viewmodel/fine_list_bloc.dart';
import '../presentation/viewmodel/map_bloc.dart';
import '../presentation/viewmodel/news_bloc.dart';
import '../presentation/viewmodel/notifications_bloc.dart';
@@ -391,6 +395,8 @@ Future setupDependencies() async {
() => OrderHistoryBloc(getIt()),
);
+ getIt.registerFactory(() => FineListBloc(getIt()));
+
getIt.registerFactory(
() => ScooterCodeBloc(
getScooterByTitleUsecase: getIt(),
@@ -409,6 +415,12 @@ Future setupDependencies() async {
ApplyPromoCodeUsecase(getIt()),
);
+ getIt.registerFactory(() => GetFinesUsecase(getIt()));
+
+ getIt.registerFactory(() => GetFineDetailsUsecase(getIt()));
+
+ getIt.registerFactory(() => PayFineUsecase(getIt()));
+
// Bloc (factory, т.к. экран создаёт новый экземпляр)
getIt.registerFactory(
() => PromoCodeBloc(getIt()),
diff --git a/lib/domain/entities/fine.dart b/lib/domain/entities/fine.dart
index 929590e..19b44f1 100644
--- a/lib/domain/entities/fine.dart
+++ b/lib/domain/entities/fine.dart
@@ -2,8 +2,9 @@ import 'package:equatable/equatable.dart';
class Fine extends Equatable {
final int id;
- final String scooterNumber;
- final String date;
+ final int orderId; // ← добавлено
+ final String scooterNumber; // можно оставить для совместимости, но не использовать в UI
+ final DateTime createdAtDateTime; // ← новое поле
final String description;
final double amount;
final String amountPrint;
@@ -12,8 +13,9 @@ class Fine extends Equatable {
const Fine({
required this.id,
+ required this.orderId,
required this.scooterNumber,
- required this.date,
+ required this.createdAtDateTime,
required this.description,
required this.amount,
required this.amountPrint,
@@ -28,22 +30,15 @@ class Fine extends Equatable {
.where((path) => path.isNotEmpty)
.toList();
- // Форматирование даты из createdAt (2026-08-07T09:15:26.565Z -> 07-08-2026)
- String formattedDate = '';
- if (json['createdAt'] != null) {
- final parsedDate = DateTime.tryParse(json['createdAt'].toString());
- if (parsedDate != null) {
- final day = parsedDate.day.toString().padLeft(2, '0');
- final month = parsedDate.month.toString().padLeft(2, '0');
- final year = parsedDate.year;
- formattedDate = '$day-$month-$year';
- }
- }
+ // Парсим createdAt как DateTime
+ final createdAtDateTime = DateTime.tryParse(json['createdAt'].toString()) ??
+ DateTime.now(); // fallback
return Fine(
id: json['id'] as int? ?? 0,
+ orderId: json['orderId'] as int? ?? 0,
scooterNumber: scooterNumber ?? '',
- date: formattedDate,
+ createdAtDateTime: createdAtDateTime,
description: json['description'] as String? ?? '',
amount: (json['value'] as num?)?.toDouble() ?? 0.0,
amountPrint: json['valuePrint'] as String? ?? '0,00 BYN',
@@ -52,21 +47,12 @@ class Fine extends Equatable {
);
}
- Map toJson() {
- return {
- 'id': id,
- 'description': description,
- 'value': amount,
- 'valuePrint': amountPrint,
- 'isPaid': isPaid,
- };
- }
-
@override
List