new project stable version
This commit is contained in:
93
lib/core/app_colors.dart
Normal file
93
lib/core/app_colors.dart
Normal file
@@ -0,0 +1,93 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppColors {
|
||||
// --------------------------
|
||||
// ФОНЫ ЭКРАНОВ
|
||||
// --------------------------
|
||||
|
||||
/// Градиент PhoneScreen (ввод телефона)
|
||||
static const LinearGradient phoneScreenBg = LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Color(0xFF293A69),
|
||||
Color(0xFF202741),
|
||||
],
|
||||
);
|
||||
|
||||
/// Градиент PhoneLoginScreen & PinLoginScreen
|
||||
static const LinearGradient authScreenBg = LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Color(0xFF0D1A44),
|
||||
Color(0xFF091233),
|
||||
],
|
||||
);
|
||||
|
||||
// --------------------------
|
||||
// КНОПКИ
|
||||
// --------------------------
|
||||
|
||||
/// Активная кнопка — бирюзово-зелёный градиент
|
||||
static const LinearGradient activeButtonGradient = LinearGradient(
|
||||
begin: Alignment.centerLeft,
|
||||
end: Alignment.centerRight,
|
||||
colors: [
|
||||
Color(0xFF75FBF0),
|
||||
Color(0xFF8BFFAA),
|
||||
],
|
||||
);
|
||||
|
||||
/// Неактивная кнопка — тёмно-синий
|
||||
static const Color disabledButtonColor = Color(0xFF2A3A6A);
|
||||
|
||||
/// Активный текст кнопки
|
||||
static const Color activeButtonText = Color(0xFF000032);
|
||||
|
||||
/// Неактивный текст кнопки
|
||||
static const Color disabledButtonText = Color(0x99FFFFFF);
|
||||
|
||||
// --------------------------
|
||||
// ЦВЕТА ДЛЯ TOGGLE / CHECKBOX
|
||||
// --------------------------
|
||||
|
||||
/// Бордер неактивного чекбокса
|
||||
static const Color checkboxBorder = Colors.white70;
|
||||
|
||||
/// Бордер чекбокса с ошибкой
|
||||
static const Color checkboxErrorBorder = Color(0xFFBA1A1A);
|
||||
|
||||
/// Цвет заливки активного чекбокса
|
||||
static const Color checkboxFill = Color(0xFF8BFFAA);
|
||||
|
||||
// --------------------------
|
||||
// PIN / CODE INPUT
|
||||
// --------------------------
|
||||
|
||||
/// Цвет цифры в SMS-коде (PhoneLoginScreen)
|
||||
static const Color smsDigit = Color(0xFF75FBF0);
|
||||
|
||||
/// Цвет точки-плейсхолдера
|
||||
static const Color digitPlaceholder = Color(0x66FFFFFF);
|
||||
|
||||
/// Цвет правильного PIN
|
||||
static const Color pinSuccess = Color(0xFF66FF99);
|
||||
|
||||
/// Цвет неверного PIN
|
||||
static const Color pinError = Color(0xFFFF4F4F);
|
||||
|
||||
// --------------------------
|
||||
// ТЕКСТ
|
||||
// --------------------------
|
||||
|
||||
static const Color whiteText = Colors.white;
|
||||
static const Color white70 = Colors.white70;
|
||||
static const Color hint = Colors.white54;
|
||||
|
||||
// --------------------------
|
||||
// ПРОЧЕЕ
|
||||
// --------------------------
|
||||
|
||||
static const Color darkBlue = Color(0xFF000032);
|
||||
}
|
||||
29
lib/core/failures.dart
Normal file
29
lib/core/failures.dart
Normal file
@@ -0,0 +1,29 @@
|
||||
sealed class EntityFailure {
|
||||
final String? message;
|
||||
const EntityFailure(this.message);
|
||||
}
|
||||
|
||||
class AuthFailure extends EntityFailure {
|
||||
final int attemptsLeft;
|
||||
const AuthFailure(this.attemptsLeft, {String? message}) : super(message);
|
||||
}
|
||||
|
||||
class AuthBlockFailure extends EntityFailure {
|
||||
const AuthBlockFailure(super.message);
|
||||
}
|
||||
|
||||
class WrongZoneFailure extends EntityFailure {
|
||||
const WrongZoneFailure(super.message);
|
||||
}
|
||||
|
||||
class ScooterNotFoundFailure extends EntityFailure {
|
||||
const ScooterNotFoundFailure(super.message);
|
||||
}
|
||||
|
||||
class RouteHistoryNotFoundFailure extends EntityFailure {
|
||||
const RouteHistoryNotFoundFailure(super.message);
|
||||
}
|
||||
|
||||
class UnknownFailure extends EntityFailure {
|
||||
const UnknownFailure(super.message);
|
||||
}
|
||||
13
lib/core/result.dart
Normal file
13
lib/core/result.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import 'failures.dart';
|
||||
|
||||
sealed class Result<T> {}
|
||||
|
||||
class Success<T> extends Result<T> {
|
||||
final T? data;
|
||||
Success(this.data);
|
||||
}
|
||||
|
||||
class Failure<T> extends Result<T> {
|
||||
final EntityFailure failure;
|
||||
Failure(this.failure);
|
||||
}
|
||||
8
lib/data/exceptions/auth_block_exception.dart
Normal file
8
lib/data/exceptions/auth_block_exception.dart
Normal file
@@ -0,0 +1,8 @@
|
||||
class AuthBlockException implements Exception {
|
||||
String description = "Неверный код. Вы временно заблокированы, попробуйте позже.";
|
||||
|
||||
AuthBlockException();
|
||||
|
||||
@override
|
||||
String toString() => description;
|
||||
}
|
||||
9
lib/data/exceptions/auth_exception.dart
Normal file
9
lib/data/exceptions/auth_exception.dart
Normal file
@@ -0,0 +1,9 @@
|
||||
class AuthException implements Exception {
|
||||
int attemptsLeft;
|
||||
String? description;
|
||||
|
||||
AuthException(this.description, this.attemptsLeft);
|
||||
|
||||
@override
|
||||
String toString() => description ?? "Ошибка авторизации";
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class RouteHistoryNotFoundException implements Exception {
|
||||
final String message;
|
||||
|
||||
RouteHistoryNotFoundException({this.message = "История маршрута не найдена"});
|
||||
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
||||
8
lib/data/exceptions/scooter_not_found_exception.dart
Normal file
8
lib/data/exceptions/scooter_not_found_exception.dart
Normal file
@@ -0,0 +1,8 @@
|
||||
class ScooterNotFoundException implements Exception {
|
||||
final String message;
|
||||
|
||||
ScooterNotFoundException({this.message = "Самокат не найден"});
|
||||
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
||||
5
lib/data/exceptions/unauthorized_exception.dart
Normal file
5
lib/data/exceptions/unauthorized_exception.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
class UnauthorizedException implements Exception {
|
||||
|
||||
@override
|
||||
String toString() => "Ошибка авторизации. Пользователь не авторизован";
|
||||
}
|
||||
6
lib/data/exceptions/wrong_zone_exception.dart
Normal file
6
lib/data/exceptions/wrong_zone_exception.dart
Normal file
@@ -0,0 +1,6 @@
|
||||
class WrongZoneException implements Exception {
|
||||
final String message;
|
||||
|
||||
WrongZoneException({required this.message});
|
||||
|
||||
}
|
||||
13
lib/data/models/auth_response_dto.dart
Normal file
13
lib/data/models/auth_response_dto.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
class AuthResponseDto {
|
||||
final String accessToken;
|
||||
final String refreshToken;
|
||||
|
||||
AuthResponseDto({required this.accessToken, required this.refreshToken});
|
||||
|
||||
factory AuthResponseDto.fromJson(Map<String, dynamic> json) {
|
||||
return AuthResponseDto(
|
||||
accessToken: json["accessToken"] ?? "",
|
||||
refreshToken: json["refreshToken"] ?? "",
|
||||
);
|
||||
}
|
||||
}
|
||||
83
lib/data/models/client_notification_dto.dart
Normal file
83
lib/data/models/client_notification_dto.dart
Normal file
@@ -0,0 +1,83 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import '../../domain/entities/client_notification.dart';
|
||||
|
||||
class ClientNotificationDto {
|
||||
final int id;
|
||||
final String content;
|
||||
final int clientId;
|
||||
final String type;
|
||||
final String category;
|
||||
final String createdAt;
|
||||
final String? canceledAt;
|
||||
final String? readAt;
|
||||
|
||||
ClientNotificationDto({
|
||||
required this.id,
|
||||
required this.content,
|
||||
required this.clientId,
|
||||
required this.type,
|
||||
required this.category,
|
||||
required this.createdAt,
|
||||
this.canceledAt,
|
||||
this.readAt,
|
||||
});
|
||||
|
||||
factory ClientNotificationDto.fromJson(Map<String, dynamic> json) {
|
||||
return ClientNotificationDto(
|
||||
id: json['id'] as int,
|
||||
content: json['content'] as String,
|
||||
clientId: json['clientId'] as int,
|
||||
type: json['type'] as String,
|
||||
category: json['category'] as String,
|
||||
createdAt: json['createdAt'] as String,
|
||||
canceledAt: json['canceledAt'] as String?,
|
||||
readAt: json['readAt'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
ClientNotification toEntity() {
|
||||
return ClientNotification(
|
||||
id: id,
|
||||
content: content,
|
||||
clientId: clientId,
|
||||
type: _parseType(type),
|
||||
category: _parseCategory(category),
|
||||
createdAt: DateTime.parse(createdAt),
|
||||
canceledAt: canceledAt != null ? DateTime.parse(canceledAt!) : null,
|
||||
readAt: readAt != null ? DateTime.parse(readAt!) : null,
|
||||
);
|
||||
}
|
||||
|
||||
NotificationType _parseType(String type) {
|
||||
switch (type.toLowerCase()) {
|
||||
case 'info':
|
||||
return NotificationType.info;
|
||||
case 'attention':
|
||||
return NotificationType.attention;
|
||||
case 'warning':
|
||||
return NotificationType.warning;
|
||||
default:
|
||||
return NotificationType.info;
|
||||
}
|
||||
}
|
||||
|
||||
NotificationCategory _parseCategory(String category) {
|
||||
switch (category.toLowerCase()) {
|
||||
case 'auth':
|
||||
return NotificationCategory.auth;
|
||||
case 'zone':
|
||||
return NotificationCategory.zone;
|
||||
case 'payment':
|
||||
return NotificationCategory.payment;
|
||||
case 'companyinfo':
|
||||
return NotificationCategory.companyInfo;
|
||||
case 'admininfo':
|
||||
return NotificationCategory.adminInfo;
|
||||
case 'scooter':
|
||||
return NotificationCategory.scooter;
|
||||
default:
|
||||
return NotificationCategory.companyInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
9
lib/data/models/login_request_dto.dart
Normal file
9
lib/data/models/login_request_dto.dart
Normal file
@@ -0,0 +1,9 @@
|
||||
class LoginRequestDto {
|
||||
final String phone;
|
||||
|
||||
LoginRequestDto({required this.phone});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {"phone": phone};
|
||||
}
|
||||
}
|
||||
25
lib/data/models/payment_card_request_dto.dart
Normal file
25
lib/data/models/payment_card_request_dto.dart
Normal file
@@ -0,0 +1,25 @@
|
||||
class PaymentCardRequestDto {
|
||||
final String cardNumber;
|
||||
final String cardHolder;
|
||||
final int expirationMonth;
|
||||
final int expirationYear;
|
||||
final String cvv;
|
||||
|
||||
PaymentCardRequestDto({
|
||||
required this.cardNumber,
|
||||
required this.cardHolder,
|
||||
required this.expirationMonth,
|
||||
required this.expirationYear,
|
||||
required this.cvv,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'cardNumber': cardNumber.replaceAll(' ', ''),
|
||||
'cardHolder': cardHolder,
|
||||
'expirationMonth': expirationMonth,
|
||||
'expirationYear': expirationYear,
|
||||
'cvv': cvv,
|
||||
};
|
||||
}
|
||||
}
|
||||
49
lib/data/models/payment_card_response_dto.dart
Normal file
49
lib/data/models/payment_card_response_dto.dart
Normal file
@@ -0,0 +1,49 @@
|
||||
import '../../domain/entities/payment_card.dart';
|
||||
|
||||
class PaymentCardResponseDto {
|
||||
final int id;
|
||||
final int clientId;
|
||||
final int expirationMonth;
|
||||
final int expirationYear;
|
||||
final String cardHolder;
|
||||
final String cardLastNumber;
|
||||
final String type;
|
||||
final bool isMain;
|
||||
|
||||
PaymentCardResponseDto({
|
||||
required this.id,
|
||||
required this.clientId,
|
||||
required this.expirationMonth,
|
||||
required this.expirationYear,
|
||||
required this.cardHolder,
|
||||
required this.cardLastNumber,
|
||||
required this.type,
|
||||
required this.isMain,
|
||||
});
|
||||
|
||||
factory PaymentCardResponseDto.fromJson(Map<String, dynamic> json) {
|
||||
return PaymentCardResponseDto(
|
||||
id: json['id'] as int,
|
||||
clientId: json['clientId'] as int,
|
||||
expirationMonth: json['expirationMonth'] as int,
|
||||
expirationYear: json['expirationYear'] as int,
|
||||
cardHolder: json['cardHolder'] as String,
|
||||
cardLastNumber: json['cardLastNumber'] as String,
|
||||
isMain: json['isMain'] as bool,
|
||||
type: json['type'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
PaymentCard toEntity(String? fullCardNumber) {
|
||||
return PaymentCard(
|
||||
id: id,
|
||||
clientId: clientId,
|
||||
expirationMonth: expirationMonth,
|
||||
expirationYear: expirationYear,
|
||||
cardHolder: cardHolder,
|
||||
cardLastNumber: cardLastNumber,
|
||||
isMain: isMain,
|
||||
type: type,
|
||||
);
|
||||
}
|
||||
}
|
||||
21
lib/data/models/scooter_order_history_response.dart
Normal file
21
lib/data/models/scooter_order_history_response.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import '../../domain/entities/scooter_order.dart';
|
||||
import '../../domain/entities/pagination.dart';
|
||||
|
||||
class ScooterOrderHistoryResponse {
|
||||
final List<ScooterOrder> orders;
|
||||
final Pagination pagination;
|
||||
|
||||
ScooterOrderHistoryResponse({
|
||||
required this.orders,
|
||||
required this.pagination,
|
||||
});
|
||||
|
||||
factory ScooterOrderHistoryResponse.fromJson(Map<String, dynamic> json) {
|
||||
return ScooterOrderHistoryResponse(
|
||||
orders: (json['data'] as List<dynamic>)
|
||||
.map((e) => ScooterOrder.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
pagination: Pagination.fromJson(json['pagination']),
|
||||
);
|
||||
}
|
||||
}
|
||||
21
lib/data/models/scooters_response.dart
Normal file
21
lib/data/models/scooters_response.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import '../../domain/entities/pagination.dart';
|
||||
import '../../domain/entities/scooter.dart';
|
||||
|
||||
class ScootersResponse {
|
||||
final List<Scooter> scooters;
|
||||
final Pagination pagination;
|
||||
|
||||
ScootersResponse({
|
||||
required this.scooters,
|
||||
required this.pagination,
|
||||
});
|
||||
|
||||
factory ScootersResponse.fromJson(Map<String, dynamic> json) {
|
||||
return ScootersResponse(
|
||||
scooters: (json['data'] as List<dynamic>)
|
||||
.map((e) => Scooter.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
pagination: Pagination.fromJson(json['pagination']),
|
||||
);
|
||||
}
|
||||
}
|
||||
15
lib/data/models/subscriptions_response.dart
Normal file
15
lib/data/models/subscriptions_response.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:be_happy/domain/entities/subscription.dart';
|
||||
|
||||
class SubscriptionsResponse {
|
||||
final List<Subscription> subscriptions;
|
||||
|
||||
SubscriptionsResponse({required this.subscriptions});
|
||||
|
||||
factory SubscriptionsResponse.fromJson(Map<String, dynamic> json) {
|
||||
return SubscriptionsResponse(
|
||||
subscriptions: (json['data'] as List<dynamic>)
|
||||
.map((e) => Subscription.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
15
lib/data/models/tariffs_response.dart
Normal file
15
lib/data/models/tariffs_response.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:be_happy/domain/entities/tariff.dart';
|
||||
|
||||
class TariffsResponse {
|
||||
final List<Tariff> tariffs;
|
||||
|
||||
TariffsResponse({required this.tariffs});
|
||||
|
||||
factory TariffsResponse.fromJson(Map<String, dynamic> json) {
|
||||
return TariffsResponse(
|
||||
tariffs: (json['data'] as List<dynamic>)
|
||||
.map((e) => Tariff.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
22
lib/data/models/user_check_response_dto.dart
Normal file
22
lib/data/models/user_check_response_dto.dart
Normal file
@@ -0,0 +1,22 @@
|
||||
class UserCheckResponseDto {
|
||||
final bool success;
|
||||
final bool hasFine;
|
||||
final bool hasUnpaidOrder;
|
||||
final bool hasCard;
|
||||
|
||||
UserCheckResponseDto({
|
||||
required this.success,
|
||||
required this.hasFine,
|
||||
required this.hasUnpaidOrder,
|
||||
required this.hasCard,
|
||||
});
|
||||
|
||||
factory UserCheckResponseDto.fromJson(Map<String, dynamic> json) {
|
||||
return UserCheckResponseDto(
|
||||
success: json['success'] ?? false,
|
||||
hasFine: json['hasFine'] ?? false,
|
||||
hasUnpaidOrder: json['hasUnpaidOrder'] ?? false,
|
||||
hasCard: json['hasCard'] ?? false,
|
||||
);
|
||||
}
|
||||
}
|
||||
10
lib/data/models/verify_code_request_dto.dart
Normal file
10
lib/data/models/verify_code_request_dto.dart
Normal file
@@ -0,0 +1,10 @@
|
||||
class VerifyCodeRequestDto {
|
||||
final String code;
|
||||
final String token;
|
||||
|
||||
VerifyCodeRequestDto({required this.code, required this.token});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {"code": code, "token": token};
|
||||
}
|
||||
}
|
||||
22
lib/data/models/zones_response.dart
Normal file
22
lib/data/models/zones_response.dart
Normal file
@@ -0,0 +1,22 @@
|
||||
import '../../domain/entities/pagination.dart';
|
||||
import '../../domain/entities/scooter.dart';
|
||||
import '../../domain/entities/zone.dart';
|
||||
|
||||
class ZonesResponse {
|
||||
final List<Zone> zones;
|
||||
final Pagination pagination;
|
||||
|
||||
ZonesResponse({
|
||||
required this.zones,
|
||||
required this.pagination,
|
||||
});
|
||||
|
||||
factory ZonesResponse.fromJson(Map<String, dynamic> json) {
|
||||
return ZonesResponse(
|
||||
zones: (json['data'] as List<dynamic>)
|
||||
.map((e) => Zone.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
pagination: Pagination.fromJson(json['pagination']),
|
||||
);
|
||||
}
|
||||
}
|
||||
1072
lib/data/network/api_service.dart
Normal file
1072
lib/data/network/api_service.dart
Normal file
File diff suppressed because it is too large
Load Diff
86
lib/data/network/geocoding_remote_datasource.dart
Normal file
86
lib/data/network/geocoding_remote_datasource.dart
Normal file
@@ -0,0 +1,86 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:yandex_mapkit/yandex_mapkit.dart';
|
||||
|
||||
class GeocodingRemoteDataSource {
|
||||
|
||||
Future<String> getAddressFromPoint({
|
||||
required double latitude,
|
||||
required double longitude,
|
||||
}) async {
|
||||
final point = Point(
|
||||
latitude: latitude,
|
||||
longitude: longitude,
|
||||
);
|
||||
|
||||
final (session, resultFuture) = await YandexSearch.searchByPoint(
|
||||
point: point,
|
||||
zoom: 16,
|
||||
searchOptions: const SearchOptions(
|
||||
searchType: SearchType.geo,
|
||||
resultPageSize: 1,
|
||||
),
|
||||
);
|
||||
|
||||
try {
|
||||
final result = await resultFuture;
|
||||
|
||||
if (result.items == null || result.items!.isEmpty) {
|
||||
throw Exception("Адрес не найден");
|
||||
}
|
||||
|
||||
final item = result.items!.first;
|
||||
|
||||
print("ADDRESS FETCH RESULT ${item.name}");
|
||||
|
||||
final toponymAddress =
|
||||
item.toponymMetadata?.address?.formattedAddress;
|
||||
|
||||
if (toponymAddress != null && toponymAddress.isNotEmpty) {
|
||||
return toponymAddress;
|
||||
}
|
||||
|
||||
final businessAddress =
|
||||
item.businessMetadata?.address?.formattedAddress;
|
||||
|
||||
if (businessAddress != null && businessAddress.isNotEmpty) {
|
||||
return businessAddress;
|
||||
}
|
||||
|
||||
return item.name;
|
||||
} catch (e) {
|
||||
throw Exception("Ошибка получения адреса: $e");
|
||||
} finally {
|
||||
await session.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<MasstransitRoute>?> getPedestrianRoutes(Point userPosition,
|
||||
Point targetPosition) async {
|
||||
final (session, resultFuture) = await YandexPedestrian.requestRoutes(
|
||||
points: [
|
||||
RequestPoint(
|
||||
point: userPosition, requestPointType: RequestPointType.wayPoint),
|
||||
RequestPoint(point: targetPosition,
|
||||
requestPointType: RequestPointType.wayPoint)
|
||||
],
|
||||
fitnessOptions: FitnessOptions(avoidSteep: false, avoidStairs: false),
|
||||
timeOptions: TimeOptions()
|
||||
);
|
||||
|
||||
try {
|
||||
final result = await resultFuture;
|
||||
|
||||
final distance = result.routes?.first.metadata.weight.walkingDistance.value;
|
||||
|
||||
print("Дистанция до самоката: $distance");
|
||||
|
||||
return result.routes;
|
||||
|
||||
} catch (e) {
|
||||
print('Error: $e');
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
42
lib/data/repositories/app_settings_repository_impl.dart
Normal file
42
lib/data/repositories/app_settings_repository_impl.dart
Normal file
@@ -0,0 +1,42 @@
|
||||
import 'package:be_happy/data/service/app_setting_service.dart';
|
||||
import 'package:be_happy/domain/entities/map_settings.dart';
|
||||
import 'package:be_happy/domain/repositories/app_settings_repository.dart';
|
||||
|
||||
class AppSettingsRepositoryImpl extends AppSettingsRepository {
|
||||
static const String SHOW_ALL_PLACEMARKS = "all_placemarks";
|
||||
static const String SHOW_ALL_ZONES = "all_zones";
|
||||
static const String SHOW_PARKING_ZONES = "parking_zones";
|
||||
static const String SHOW_RESTRICTED_PARKING_ZONES = "restricted_parking_zones";
|
||||
static const String SHOW_RESTRICTED_DRIVING_ZONES = "restricted_driving_zones";
|
||||
|
||||
final AppSettingsService appSettingsService;
|
||||
|
||||
AppSettingsRepositoryImpl(this.appSettingsService);
|
||||
|
||||
@override
|
||||
Future<MapSettings> getMapSettings() async {
|
||||
MapSettings settings = MapSettings(
|
||||
all_placemarks: appSettingsService.getMapSettingsFlag(
|
||||
SHOW_ALL_PLACEMARKS),
|
||||
all_zones: appSettingsService.getMapSettingsFlag(
|
||||
SHOW_ALL_ZONES),
|
||||
parking_zones: appSettingsService.getMapSettingsFlag(
|
||||
SHOW_PARKING_ZONES),
|
||||
restricted_parking_zones: appSettingsService.getMapSettingsFlag(
|
||||
SHOW_RESTRICTED_PARKING_ZONES),
|
||||
restricted_driving_zones: appSettingsService.getMapSettingsFlag(
|
||||
SHOW_RESTRICTED_DRIVING_ZONES)
|
||||
);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveMapSettings(MapSettings settings) async {
|
||||
appSettingsService.saveMapSettingsFlag(SHOW_ALL_PLACEMARKS, settings.all_placemarks);
|
||||
appSettingsService.saveMapSettingsFlag(SHOW_ALL_ZONES, settings.all_zones);
|
||||
appSettingsService.saveMapSettingsFlag(SHOW_PARKING_ZONES, settings.parking_zones);
|
||||
appSettingsService.saveMapSettingsFlag(SHOW_RESTRICTED_PARKING_ZONES, settings.restricted_parking_zones);
|
||||
appSettingsService.saveMapSettingsFlag(SHOW_RESTRICTED_DRIVING_ZONES, settings.restricted_driving_zones);
|
||||
}
|
||||
}
|
||||
85
lib/data/repositories/auth_repository_impl.dart
Normal file
85
lib/data/repositories/auth_repository_impl.dart
Normal file
@@ -0,0 +1,85 @@
|
||||
import 'package:be_happy/core/failures.dart';
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/data/exceptions/auth_block_exception.dart';
|
||||
import 'package:be_happy/data/exceptions/auth_exception.dart';
|
||||
import 'package:be_happy/data/repositories/pin_repository_impl.dart';
|
||||
import 'package:be_happy/domain/service/device_info_service.dart';
|
||||
import 'package:be_happy/domain/service/security_service.dart';
|
||||
|
||||
import '../../domain/repositories/auth_repository.dart';
|
||||
import '../../domain/entities/user_auth_data.dart';
|
||||
|
||||
import '../network/api_service.dart';
|
||||
|
||||
class AuthRepositoryImpl implements AuthRepository {
|
||||
final ApiService _apiService;
|
||||
final DeviceInfoService _deviceInfoService;
|
||||
final SecurityService _securityService;
|
||||
|
||||
String tempToken = "";
|
||||
|
||||
AuthRepositoryImpl(
|
||||
this._apiService,
|
||||
this._deviceInfoService,
|
||||
this._securityService,
|
||||
);
|
||||
|
||||
@override
|
||||
Future<String> login(String phone) async {
|
||||
final systemId = await _deviceInfoService.getSystemId() ?? "UnknownId";
|
||||
final deviceModel = await _deviceInfoService.getDeviceModel();
|
||||
|
||||
final response = await _apiService.sendPhone(phone, deviceModel, systemId);
|
||||
if (response != null) {
|
||||
tempToken = response;
|
||||
print("TEMP TOKEN IS $tempToken");
|
||||
return response;
|
||||
} else {
|
||||
throw Exception("Login failed");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> verifyCode(String code, String token) async {
|
||||
late final Result<UserAuthData> result;
|
||||
try {
|
||||
final response = await _apiService.verifyCode(code, tempToken);
|
||||
if (response != null) {
|
||||
final authData = UserAuthData(
|
||||
accessToken: response["accessToken"]!,
|
||||
refreshToken: response["refreshToken"]!,
|
||||
);
|
||||
await _securityService.saveTokens(authData);
|
||||
result = Success(null);
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} on AuthBlockException {
|
||||
result = Failure(AuthBlockFailure("Ошибка. Вы заблокированы."));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<UserAuthData> refreshToken() async {
|
||||
final response = await _apiService.refresh();
|
||||
print("REFRESH: $response");
|
||||
if (response != null) {
|
||||
final authData = UserAuthData(
|
||||
accessToken: response["accessToken"]!,
|
||||
refreshToken: response["refreshToken"]!,
|
||||
);
|
||||
await _securityService.saveTokens(authData);
|
||||
return authData;
|
||||
} else {
|
||||
throw Exception("Refresh token failed");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> logout() async {
|
||||
await _securityService.removeTokens();
|
||||
}
|
||||
}
|
||||
59
lib/data/repositories/certificate_repository_impl.dart
Normal file
59
lib/data/repositories/certificate_repository_impl.dart
Normal file
@@ -0,0 +1,59 @@
|
||||
import '../../core/failures.dart';
|
||||
import '../../core/result.dart';
|
||||
import '../../domain/entities/certificate.dart';
|
||||
import '../../domain/repositories/certificate_repository.dart';
|
||||
import '../../domain/service/security_service.dart';
|
||||
import '../network/api_service.dart';
|
||||
import '../exceptions/auth_exception.dart';
|
||||
import '../exceptions/auth_block_exception.dart';
|
||||
import '../exceptions/unauthorized_exception.dart';
|
||||
|
||||
class CertificateRepositoryImpl implements CertificateRepository {
|
||||
final ApiService apiService;
|
||||
final SecurityService securityService;
|
||||
|
||||
CertificateRepositoryImpl(this.apiService, this.securityService);
|
||||
|
||||
@override
|
||||
Future<Result<List<Certificate>>> getCertificates() async {
|
||||
try {
|
||||
final certificates = await apiService.getCertificates();
|
||||
return Success(certificates);
|
||||
} on AuthException catch (e) {
|
||||
return Failure(AuthFailure(e.attemptsLeft));
|
||||
} on AuthBlockException catch (_) {
|
||||
return Failure(AuthBlockFailure("Ошибка. Вы заблокированы."));
|
||||
} on UnauthorizedException catch (_) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
} catch (e) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Map<String, dynamic>>> purchaseCertificate({
|
||||
required int certificateId,
|
||||
required int cardId,
|
||||
}) async {
|
||||
try {
|
||||
final result = await apiService.purchaseCertificate(
|
||||
certificateId: certificateId,
|
||||
cardId: cardId,
|
||||
);
|
||||
|
||||
if (result != null) {
|
||||
return Success(result);
|
||||
} else {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
return Failure(AuthFailure(e.attemptsLeft));
|
||||
} on AuthBlockException catch (_) {
|
||||
return Failure(AuthBlockFailure("Ошибка. Вы заблокированы."));
|
||||
} on UnauthorizedException catch (_) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
} catch (e) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
}
|
||||
}
|
||||
46
lib/data/repositories/news_repository_impl.dart
Normal file
46
lib/data/repositories/news_repository_impl.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
import '../../domain/entities/news.dart';
|
||||
import '../../domain/repositories/news_repository.dart';
|
||||
import '../service/news_api_service.dart';
|
||||
import 'dart:developer' as dev;
|
||||
|
||||
class NewsRepositoryImpl implements NewsRepository {
|
||||
final NewsApiService _apiService;
|
||||
|
||||
NewsRepositoryImpl(this._apiService);
|
||||
|
||||
@override
|
||||
Future<List<NewsEntity>> getNews() async {
|
||||
try {
|
||||
dev.log('NewsRepository: Загрузка новостей...');
|
||||
|
||||
final response = await _apiService.getNews();
|
||||
final List<dynamic> data = response['data'] ?? [];
|
||||
|
||||
final newsList = data.map((json) => NewsEntity.fromJson(json)).toList();
|
||||
|
||||
dev.log('NewsRepository: Загружено ${newsList.length} новостей');
|
||||
|
||||
return newsList;
|
||||
} catch (e, stackTrace) {
|
||||
dev.log('NewsRepository: Ошибка: $e', stackTrace: stackTrace);
|
||||
throw Exception('Не удалось загрузить новости: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<NewsEntity> getNewsById(int id) async {
|
||||
try {
|
||||
dev.log('NewsRepository: Загрузка новости с ID: $id');
|
||||
|
||||
final response = await _apiService.getNewsById(id);
|
||||
|
||||
final news = NewsEntity.fromJson(response);
|
||||
|
||||
dev.log('NewsRepository: Успешно загружена новость с ID: $id');
|
||||
return news;
|
||||
} catch (e, stackTrace) {
|
||||
dev.log('NewsRepository: Ошибка: $e', stackTrace: stackTrace);
|
||||
throw Exception('Не удалось загрузить новость: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
36
lib/data/repositories/notification_repository_impl.dart
Normal file
36
lib/data/repositories/notification_repository_impl.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'package:be_happy/domain/entities/client_notification.dart';
|
||||
|
||||
import '../../data/network/api_service.dart';
|
||||
import '../../domain/repositories/notification_repository.dart';
|
||||
import '../models/client_notification_dto.dart';
|
||||
|
||||
class NotificationRepositoryImpl implements NotificationRepository {
|
||||
final ApiService _apiService;
|
||||
|
||||
NotificationRepositoryImpl(this._apiService);
|
||||
|
||||
@override
|
||||
Stream<ClientNotification> getNotificationsStream() {
|
||||
return _apiService.getNotificationsStream().map((data) {
|
||||
// Создаем DTO из данных API
|
||||
final dto = ClientNotificationDto.fromJson(data);
|
||||
// Преобразуем в entity
|
||||
return dto.toEntity();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ClientNotification> cancelNotification(int id) async {
|
||||
final data = await _apiService.cancelNotification(id);
|
||||
if (data == null) {
|
||||
throw Exception("Failed to cancel notification");
|
||||
}
|
||||
final dto = ClientNotificationDto.fromJson(data);
|
||||
return dto.toEntity();
|
||||
}
|
||||
|
||||
@override
|
||||
void closeStream() {
|
||||
// соединение закрывается автоматически при отписке от stream
|
||||
}
|
||||
}
|
||||
116
lib/data/repositories/payment_repository_impl.dart
Normal file
116
lib/data/repositories/payment_repository_impl.dart
Normal file
@@ -0,0 +1,116 @@
|
||||
import '../../core/failures.dart';
|
||||
import '../../core/result.dart';
|
||||
import '../../domain/entities/payment_card.dart';
|
||||
import '../../domain/repositories/payment_repository.dart';
|
||||
import '../../domain/service/security_service.dart';
|
||||
import '../network/api_service.dart';
|
||||
import '../exceptions/auth_exception.dart';
|
||||
import '../exceptions/auth_block_exception.dart';
|
||||
import '../exceptions/unauthorized_exception.dart';
|
||||
import '../service/security_service_impl.dart';
|
||||
|
||||
class PaymentRepositoryImpl implements PaymentRepository {
|
||||
final ApiService apiService;
|
||||
final SecurityService securityService;
|
||||
|
||||
PaymentRepositoryImpl(this.apiService, this.securityService);
|
||||
|
||||
@override
|
||||
Future<Result<List<PaymentCard>>> getPaymentCards() async {
|
||||
try {
|
||||
final cards = await apiService.getPaymentCards();
|
||||
return Success(cards);
|
||||
} on AuthException catch (e) {
|
||||
return Failure(AuthFailure(e.attemptsLeft));
|
||||
} on AuthBlockException catch (_) {
|
||||
return Failure(AuthBlockFailure("Ошибка. Вы заблокированы."));
|
||||
} on UnauthorizedException catch (_) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
} catch (e) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> addPaymentCard({
|
||||
required String cardNumber,
|
||||
required String cardHolder,
|
||||
required String expiryMonth,
|
||||
required String expiryYear,
|
||||
required String cvv,
|
||||
}) async {
|
||||
try {
|
||||
final cardId = await apiService.addPaymentCard(
|
||||
cardNumber: cardNumber,
|
||||
cardHolder: cardHolder,
|
||||
expirationMonth: int.parse(expiryMonth),
|
||||
expirationYear: int.parse(expiryYear),
|
||||
cvv: cvv,
|
||||
);
|
||||
|
||||
// Сохраняем полный номер карты локально
|
||||
await securityService.saveCardFullNumber(cardId, cardNumber);
|
||||
|
||||
return Success(null);
|
||||
} on AuthException catch (e) {
|
||||
return Failure(AuthFailure(e.attemptsLeft));
|
||||
} on AuthBlockException catch (_) {
|
||||
return Failure(AuthBlockFailure("Ошибка. Вы заблокированы."));
|
||||
} on UnauthorizedException catch (_) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
} on FormatException catch (_) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
} catch (e) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> setMainPaymentCard(int cardId) async {
|
||||
try {
|
||||
await apiService.setMainPaymentCard(cardId);
|
||||
return Success(null);
|
||||
} on AuthException catch (e) {
|
||||
return Failure(AuthFailure(e.attemptsLeft));
|
||||
} on AuthBlockException catch (_) {
|
||||
return Failure(AuthBlockFailure("Ошибка. Вы заблокированы."));
|
||||
} on UnauthorizedException catch (_) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
} catch (e) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> removePaymentCard(int cardId) async {
|
||||
try {
|
||||
await apiService.removePaymentCard(cardId);
|
||||
await securityService.removeCardFullNumber(cardId);
|
||||
return Success(null);
|
||||
} on AuthException catch (e) {
|
||||
return Failure(AuthFailure(e.attemptsLeft));
|
||||
} on AuthBlockException catch (_) {
|
||||
return Failure(AuthBlockFailure("Ошибка. Вы заблокированы."));
|
||||
} on UnauthorizedException catch (_) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
} catch (e) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<bool>> activateSubscription(int optionId) async {
|
||||
try {
|
||||
final success = await apiService.activateSubscription(optionId: optionId);
|
||||
return Success(success);
|
||||
} on AuthException catch (e) {
|
||||
return Failure(AuthFailure(e.attemptsLeft));
|
||||
} on AuthBlockException catch (_) {
|
||||
return Failure(AuthBlockFailure("Ошибка. Вы заблокированы."));
|
||||
} on UnauthorizedException catch (_) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
} catch (e) {
|
||||
return Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
}
|
||||
}
|
||||
24
lib/data/repositories/pin_repository_impl.dart
Normal file
24
lib/data/repositories/pin_repository_impl.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
import 'package:be_happy/domain/repositories/pin_repository.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
|
||||
class PinRepositoryImpl implements PinRepository {
|
||||
final FlutterSecureStorage _storage;
|
||||
|
||||
PinRepositoryImpl(this._storage);
|
||||
|
||||
@override
|
||||
Future<String?> getSavedPin() {
|
||||
return _storage.read(key: "user_pin");
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> savePin(String? pin) async {
|
||||
await _storage.write(key: "user_pin", value: pin);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> removePin() async {
|
||||
await _storage.delete(key: "user_pin");
|
||||
}
|
||||
}
|
||||
|
||||
48
lib/data/repositories/profile_repository_impl.dart
Normal file
48
lib/data/repositories/profile_repository_impl.dart
Normal file
@@ -0,0 +1,48 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:be_happy/data/network/api_service.dart';
|
||||
|
||||
import '../../domain/entities/user_profile.dart';
|
||||
import '../../domain/entities/user_check_flags.dart';
|
||||
import '../../domain/repositories/profile_repository.dart';
|
||||
|
||||
class UserProfileRepositoryImpl implements UserProfileRepository {
|
||||
final ApiService _apiService;
|
||||
|
||||
static const String kAccessToken = "access_token";
|
||||
static const String kRefreshToken = "refresh_token";
|
||||
|
||||
final UserProfile _cachedProfile = UserProfile(
|
||||
name: 'Иванов Антон',
|
||||
birthDate: '12-03-2005',
|
||||
phone: '+375 00 000-00-00',
|
||||
balance: null,
|
||||
email: 'почта@gmail.com',
|
||||
);
|
||||
|
||||
UserProfileRepositoryImpl(this._apiService);
|
||||
|
||||
@override
|
||||
Future<UserProfile> getProfile() async {
|
||||
return await _apiService.getProfile() ?? _cachedProfile;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<UserProfile?> updateProfile(UserProfile profile) async {
|
||||
//await Future.delayed(const Duration(milliseconds: 300));
|
||||
print("UPDATE PROFILE DATA: $profile");
|
||||
return await _apiService.updateProfile(profile);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int?> uploadProfilePhoto(File imageFile) async {
|
||||
return await _apiService.uploadPhoto(imageFile);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<UserCheckFlags?> checkUser() async {
|
||||
return await _apiService.checkUser();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
444
lib/data/repositories/scooter_repository_impl.dart
Normal file
444
lib/data/repositories/scooter_repository_impl.dart
Normal file
@@ -0,0 +1,444 @@
|
||||
import 'dart:io';
|
||||
import 'package:be_happy/data/exceptions/auth_block_exception.dart';
|
||||
import 'package:be_happy/data/exceptions/route_history_not_found_exception.dart';
|
||||
import 'package:be_happy/data/exceptions/scooter_not_found_exception.dart';
|
||||
import 'package:be_happy/data/exceptions/unauthorized_exception.dart';
|
||||
import 'package:be_happy/data/exceptions/wrong_zone_exception.dart';
|
||||
import 'package:be_happy/domain/entities/point.dart';
|
||||
import 'package:be_happy/domain/repositories/scooter_repository.dart';
|
||||
|
||||
import '../../core/failures.dart';
|
||||
import '../../core/result.dart';
|
||||
import '../../domain/entities/active_scooter_order.dart';
|
||||
import '../../domain/entities/scooter.dart';
|
||||
import '../../domain/entities/tariff.dart';
|
||||
import '../../domain/entities/subscription.dart';
|
||||
import '../../domain/entities/scooter_order.dart';
|
||||
import '../exceptions/auth_exception.dart';
|
||||
import '../network/api_service.dart';
|
||||
|
||||
class ScooterRepositoryImpl extends ScooterRepository {
|
||||
final ApiService _apiService;
|
||||
|
||||
final scooter = Scooter(
|
||||
id: 123,
|
||||
title: "Unnamed",
|
||||
status: "Available",
|
||||
latitude: 55.178960,
|
||||
longitude: 30.222316,
|
||||
batteryLevel: 89,
|
||||
isOnline: true,
|
||||
maxSpeed: 25,
|
||||
number: "Unnamed",
|
||||
);
|
||||
|
||||
ScooterRepositoryImpl(this._apiService);
|
||||
|
||||
@override
|
||||
Future<List<Scooter>> getScooters(
|
||||
List<double> area,
|
||||
int page,
|
||||
int pageSize,
|
||||
) async {
|
||||
final responce = await _apiService.getScooters(
|
||||
area: area,
|
||||
page: page,
|
||||
pageSize: pageSize,
|
||||
);
|
||||
|
||||
final List<Scooter>? list = responce?.scooters;
|
||||
// list?.add(scooter);
|
||||
|
||||
// print("Scooters: ${list?.first.status}");
|
||||
|
||||
if (responce != null) {
|
||||
return list ?? List.empty();
|
||||
}
|
||||
|
||||
return List.empty();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Scooter?>> getScooter(int id) async {
|
||||
late final Result<Scooter> result;
|
||||
try {
|
||||
final scooter = await _apiService.getScooterById(id: id);
|
||||
if (scooter != null) {
|
||||
result = Success(scooter);
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<Tariff>>> getAvailableTariffs(int scooterId) async {
|
||||
late final Result<List<Tariff>> result;
|
||||
try {
|
||||
final response = await _apiService.getAvailableTariffs(
|
||||
scooterId: scooterId,
|
||||
);
|
||||
if (response != null) {
|
||||
result = Success(response.tariffs);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<Subscription>>> getAvailableSubscriptions() async {
|
||||
late final Result<List<Subscription>> result;
|
||||
try {
|
||||
final response = await _apiService.getAvailableSubscriptions();
|
||||
if (response != null) {
|
||||
result = Success(response.subscriptions);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Subscription>> getSubscriptionById(int id) async {
|
||||
late final Result<Subscription> result;
|
||||
try {
|
||||
final subscription = await _apiService.getSubscriptionById(id: id);
|
||||
if (subscription != null) {
|
||||
result = Success(subscription);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<Subscription>>> getClientSubscriptions() async {
|
||||
late final Result<List<Subscription>> result;
|
||||
try {
|
||||
final subscriptions = await _apiService.getClientSubscriptions();
|
||||
result = Success(subscriptions);
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<ScooterOrder>> bookScooter({
|
||||
required int scooterId,
|
||||
required int planId,
|
||||
int? subscriptionId,
|
||||
int? cardId,
|
||||
required bool isBalance,
|
||||
required bool isInsurance,
|
||||
}) async {
|
||||
late final Result<ScooterOrder> result;
|
||||
try {
|
||||
final order = await _apiService.bookScooter(
|
||||
scooterId: scooterId,
|
||||
planId: planId,
|
||||
subscriptionId: subscriptionId,
|
||||
cardId: cardId,
|
||||
isBalance: isBalance,
|
||||
isInsurance: isInsurance,
|
||||
);
|
||||
if (order != null) {
|
||||
result = Success(order);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<ScooterOrder>> startRide(int orderId) async {
|
||||
late final Result<ScooterOrder> result;
|
||||
try {
|
||||
final order = await _apiService.startRide(orderId);
|
||||
if (order != null) {
|
||||
result = Success(order);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<ScooterOrder>> cancelRide(int orderId) async {
|
||||
late final Result<ScooterOrder> result;
|
||||
try {
|
||||
final order = await _apiService.cancelRide(orderId);
|
||||
if (order != null) {
|
||||
result = Success(order);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<ScooterOrder>> pauseRide(int orderId) async {
|
||||
late final Result<ScooterOrder> result;
|
||||
try {
|
||||
final order = await _apiService.pauseRide(orderId);
|
||||
if (order != null) {
|
||||
result = Success(order);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<ScooterOrder>> resumeRide(int orderId) async {
|
||||
late final Result<ScooterOrder> result;
|
||||
try {
|
||||
final order = await _apiService.resumeRide(orderId);
|
||||
if (order != null) {
|
||||
result = Success(order);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<ScooterOrder>> finishRide(int orderId, List<int> files) async {
|
||||
late final Result<ScooterOrder> result;
|
||||
try {
|
||||
final order = await _apiService.finishRide(
|
||||
orderId: orderId,
|
||||
filesId: files,
|
||||
);
|
||||
if (order != null) {
|
||||
result = Success(order);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} on WrongZoneException catch (e) {
|
||||
result = Failure(WrongZoneFailure(e.message));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<ScooterOrder>> payRide(int orderId) async {
|
||||
late final Result<ScooterOrder> result;
|
||||
try {
|
||||
final order = await _apiService.payRide(orderId);
|
||||
if (order != null) {
|
||||
result = Success(order);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<ScooterOrder>>> getClientOrders() async {
|
||||
late final Result<List<ScooterOrder>> result;
|
||||
try {
|
||||
final orders = await _apiService.getClientOrders();
|
||||
result = Success(orders);
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<int>>> uploadScooterPhotos(List<File> images) async {
|
||||
late final Result<List<int>> result;
|
||||
try {
|
||||
final filesId = await _apiService.uploadScooterPhotos(images);
|
||||
result = Success(filesId);
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<ActiveScooterOrder>> updateScooterOrderData({
|
||||
required int orderId,
|
||||
}) async {
|
||||
late final Result<ActiveScooterOrder> result;
|
||||
try {
|
||||
final order = await _apiService.updateScooterOrderData(orderId: orderId);
|
||||
if (order != null) {
|
||||
print("ORDER DATA FROM REPOSITORY: $order");
|
||||
result = Success(order);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<ScooterOrder>> payScooterOrderWithPhotos({
|
||||
required int orderId,
|
||||
required int? cardId,
|
||||
required bool isBalance,
|
||||
}) async {
|
||||
late final Result<ScooterOrder> result;
|
||||
try {
|
||||
final order = await _apiService.payScooterOrderWithPhotos(
|
||||
orderId: orderId,
|
||||
cardId: cardId,
|
||||
isBalance: isBalance,
|
||||
);
|
||||
if (order != null) {
|
||||
result = Success(order);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<ScooterOrder>> getScooterOrderById(int id) async {
|
||||
late final Result<ScooterOrder> result;
|
||||
try {
|
||||
final order = await _apiService.getScooterOrderById(id: id);
|
||||
if (order != null) {
|
||||
result = Success(order);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<ScooterOrder>>> getScooterOrderHistory({
|
||||
int page = 1,
|
||||
int pageSize = 20,
|
||||
}) async {
|
||||
late final Result<List<ScooterOrder>> result;
|
||||
try {
|
||||
final response = await _apiService.getScooterOrderHistory(
|
||||
page: page,
|
||||
pageSize: pageSize,
|
||||
);
|
||||
final List<dynamic> data = response['data'] ?? [];
|
||||
final orders = data.map((json) => ScooterOrder.fromJson(json)).toList();
|
||||
result = Success(orders);
|
||||
} on AuthException catch (e) {
|
||||
result = Failure(AuthFailure(e.attemptsLeft));
|
||||
} catch (e) {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Scooter?>> getScooterByTitle(String title) async {
|
||||
late final Result<Scooter?> result;
|
||||
try {
|
||||
final scooter = await _apiService.getScooterByTitle(title: title);
|
||||
if (scooter != null) {
|
||||
result = Success(scooter);
|
||||
} else {
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
} on ScooterNotFoundException catch (e) {
|
||||
result = Failure(ScooterNotFoundFailure(e.message));
|
||||
} on UnauthorizedException catch (e) {
|
||||
result = Failure(AuthFailure(0, message: e.toString()));
|
||||
} on AuthBlockException catch (e) {
|
||||
result = Failure(AuthBlockFailure(e.toString()));
|
||||
} catch (e, stacktrace) {
|
||||
print("REPOSITORY ERROR: $e");
|
||||
print("STACKTRACE: $stacktrace");
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<Point>>> getScooterOrderRouteHistory(int id) async {
|
||||
late final Result<List<Point>> result;
|
||||
try {
|
||||
final route = await _apiService.getScooterOrderRouteHistory(id: id);
|
||||
result = Success(route);
|
||||
} on RouteHistoryNotFoundException catch (e) {
|
||||
result = Failure(RouteHistoryNotFoundFailure(e.message));
|
||||
} on UnauthorizedException catch (e) {
|
||||
result = Failure(AuthFailure(0, message: e.toString()));
|
||||
} on AuthBlockException catch (e) {
|
||||
result = Failure(AuthBlockFailure(e.toString()));
|
||||
} catch (e, stacktrace) {
|
||||
print("REPOSITORY ERROR: $e");
|
||||
print("STACKTRACE: $stacktrace");
|
||||
result = Failure(UnknownFailure("Неизвестная ошибка"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
69
lib/data/repositories/zone_repository_impl.dart
Normal file
69
lib/data/repositories/zone_repository_impl.dart
Normal file
@@ -0,0 +1,69 @@
|
||||
import 'package:be_happy/domain/entities/zone.dart';
|
||||
import 'package:be_happy/domain/repositories/zone_repository.dart';
|
||||
|
||||
import '../../domain/entities/point.dart';
|
||||
import '../network/api_service.dart';
|
||||
|
||||
class ZoneRepositoryImpl extends ZoneRepository {
|
||||
final ApiService _apiService;
|
||||
|
||||
ZoneRepositoryImpl(this._apiService);
|
||||
|
||||
@override
|
||||
Future<List<Zone>> getZones(List<double> area,
|
||||
int page,
|
||||
int pageSize,) async {
|
||||
|
||||
final List<Point> list = [];
|
||||
final List<Point> list2 = [];
|
||||
|
||||
/*list.add(Point(55.182372,30.203347));
|
||||
list.add(Point(55.173746,30.200257));
|
||||
list.add(Point(55.172153,30.212531));
|
||||
list.add(Point(55.179946,30.215964));
|
||||
|
||||
list2.add(Point(55.178304,30.227380));
|
||||
list2.add(Point(55.178059,30.229654));
|
||||
list2.add(Point(55.191339,30.234718));
|
||||
list2.add(Point(55.194352,30.234890));
|
||||
list2.add(Point(55.194377,30.231972));
|
||||
list2.add(Point(55.192123,30.232744));
|
||||
|
||||
final zone = Zone(id: 123,
|
||||
title: "Zone 01",
|
||||
description: "description",
|
||||
type: "Finish",
|
||||
isActive: true,
|
||||
shapeType: "polygon",
|
||||
points: list,
|
||||
speedLimit: "speedLimit");
|
||||
|
||||
final zone2 = Zone(id: 124,
|
||||
title: "Zone 02",
|
||||
description: "description",
|
||||
type: "NotDrive",
|
||||
isActive: true,
|
||||
shapeType: "polygon",
|
||||
points: list2,
|
||||
speedLimit: "speedLimit");
|
||||
*/
|
||||
|
||||
final responce = await _apiService.getZones(
|
||||
area: area,
|
||||
page: page,
|
||||
pageSize: pageSize,
|
||||
);
|
||||
|
||||
final List<Zone>? zones = responce?.zones;
|
||||
// zones?.add(zone);
|
||||
// zones?.add(zone2);
|
||||
|
||||
print("Scooters: ${zones?.first.title}");
|
||||
|
||||
if (responce != null) {
|
||||
return zones ?? List.empty();
|
||||
}
|
||||
|
||||
return List.empty();
|
||||
}
|
||||
}
|
||||
15
lib/data/service/app_setting_service.dart
Normal file
15
lib/data/service/app_setting_service.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class AppSettingsService {
|
||||
final SharedPreferences sharedPreferences;
|
||||
|
||||
AppSettingsService(this.sharedPreferences);
|
||||
|
||||
Future<void> saveMapSettingsFlag(String key, bool value) async {
|
||||
sharedPreferences.setBool(key, value);
|
||||
}
|
||||
|
||||
bool getMapSettingsFlag(String key) {
|
||||
return sharedPreferences.getBool(key) ?? false;
|
||||
}
|
||||
}
|
||||
43
lib/data/service/device_info_service_impl.dart
Normal file
43
lib/data/service/device_info_service_impl.dart
Normal file
@@ -0,0 +1,43 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:android_id/android_id.dart';
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
|
||||
import '../../domain/service/device_info_service.dart';
|
||||
|
||||
class DeviceInfoServiceImpl extends DeviceInfoService {
|
||||
final DeviceInfoPlugin _deviceInfo = DeviceInfoPlugin();
|
||||
final AndroidId _androidId = const AndroidId();
|
||||
|
||||
@override
|
||||
Future<String> getDeviceModel() async {
|
||||
try {
|
||||
if (Platform.isAndroid) {
|
||||
final androidInfo = await _deviceInfo.androidInfo;
|
||||
return '${androidInfo.manufacturer} ${androidInfo.model}';
|
||||
} else if (Platform.isIOS) {
|
||||
final iosInfo = await _deviceInfo.iosInfo;
|
||||
return iosInfo.utsname.machine;
|
||||
}
|
||||
} catch (e) {
|
||||
print("ERROR: $e");
|
||||
}
|
||||
return 'Unknown';
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> getSystemId() async {
|
||||
try {
|
||||
if (Platform.isAndroid) {
|
||||
return await _androidId.getId();
|
||||
} else if (Platform.isIOS) {
|
||||
final iosInfo = await _deviceInfo.iosInfo;
|
||||
return iosInfo.identifierForVendor;
|
||||
}
|
||||
} catch (e) {
|
||||
print("ERROR: $e");
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
36
lib/data/service/news_api_service.dart
Normal file
36
lib/data/service/news_api_service.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'dart:developer' as dev;
|
||||
import '../network/api_service.dart';
|
||||
|
||||
class NewsApiService {
|
||||
final ApiService _apiService;
|
||||
|
||||
NewsApiService(this._apiService);
|
||||
|
||||
Future<Map<String, dynamic>> getNews() async {
|
||||
try {
|
||||
dev.log('NewsApiService: Запрос GET /news');
|
||||
|
||||
final response = await _apiService.getNews();
|
||||
|
||||
dev.log('NewsApiService: Успешно получено ${response['data']?.length ?? 0} новостей');
|
||||
return response;
|
||||
} catch (e, stackTrace) {
|
||||
dev.log('NewsApiService: Ошибка: $e', stackTrace: stackTrace);
|
||||
throw Exception('Не удалось загрузить новости: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getNewsById(int newsId) async {
|
||||
try {
|
||||
dev.log('NewsApiService: Запрос GET /news/$newsId');
|
||||
|
||||
final response = await _apiService.getNewsById(newsId);
|
||||
|
||||
dev.log('NewsApiService: Успешно получена новость с ID: $newsId');
|
||||
return response!;
|
||||
} catch (e, stackTrace) {
|
||||
dev.log('NewsApiService: Ошибка: $e', stackTrace: stackTrace);
|
||||
throw Exception('Не удалось загрузить новость: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
80
lib/data/service/security_service_impl.dart
Normal file
80
lib/data/service/security_service_impl.dart
Normal file
@@ -0,0 +1,80 @@
|
||||
import 'package:be_happy/domain/entities/user_auth_data.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
|
||||
import '../../domain/service/security_service.dart';
|
||||
|
||||
class SecurityServiceImpl extends SecurityService {
|
||||
static const String kAccessToken = "access_token";
|
||||
static const String kRefreshToken = "refresh_token";
|
||||
static const String kCardNumberPrefix = "card_number_";
|
||||
|
||||
final FlutterSecureStorage _secureStorage;
|
||||
|
||||
SecurityServiceImpl(this._secureStorage);
|
||||
|
||||
@override
|
||||
Future<void> saveTokens(UserAuthData data) async {
|
||||
await _secureStorage.write(key: kAccessToken, value: data.accessToken);
|
||||
await _secureStorage.write(key: kRefreshToken, value: data.refreshToken);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> removeTokens() async {
|
||||
await _secureStorage.delete(key: kRefreshToken);
|
||||
await _secureStorage.delete(key: kAccessToken);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> getAccessToken() async {
|
||||
return await _secureStorage.read(key: kAccessToken);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> getRefreshToken() async {
|
||||
return await _secureStorage.read(key: kRefreshToken);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveCardFullNumber(int cardId, String fullCardNumber) async {
|
||||
await _secureStorage.write(
|
||||
key: '${kCardNumberPrefix}_$cardId',
|
||||
value: fullCardNumber,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> getCardFullNumber(int cardId) async {
|
||||
return await _secureStorage.read(key: '${kCardNumberPrefix}_$cardId');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> removeCardFullNumber(int cardId) async {
|
||||
await _secureStorage.delete(key: '${kCardNumberPrefix}_$cardId');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearAllCardsNumbers() async {
|
||||
// Получаем все ключи и удаляем те, что начинаются с префикса карты
|
||||
final allKeys = await _secureStorage.readAll();
|
||||
for (final key in allKeys.keys) {
|
||||
if (key.startsWith(kCardNumberPrefix)) {
|
||||
await _secureStorage.delete(key: key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @override
|
||||
// Future<UserAuthData?> getTokens() async {
|
||||
// final accessToken = await _secureStorage.read(key: kAccessToken);
|
||||
// final refreshToken = await _secureStorage.read(key: kRefreshToken);
|
||||
//
|
||||
// if(accessToken != null && refreshToken != null) {
|
||||
// return UserAuthData(
|
||||
// accessToken: accessToken,
|
||||
// refreshToken: refreshToken,
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
}
|
||||
374
lib/di/service_locator.dart
Normal file
374
lib/di/service_locator.dart
Normal file
@@ -0,0 +1,374 @@
|
||||
import 'package:be_happy/data/repositories/app_settings_repository_impl.dart';
|
||||
import 'package:be_happy/data/repositories/certificate_repository_impl.dart';
|
||||
import 'package:be_happy/data/repositories/notification_repository_impl.dart';
|
||||
import 'package:be_happy/data/repositories/payment_repository_impl.dart'; // ← новый
|
||||
import 'package:be_happy/data/repositories/scooter_repository_impl.dart';
|
||||
import 'package:be_happy/data/repositories/zone_repository_impl.dart';
|
||||
import 'package:be_happy/data/service/app_setting_service.dart';
|
||||
import 'package:be_happy/data/service/device_info_service_impl.dart';
|
||||
import 'package:be_happy/data/service/security_service_impl.dart';
|
||||
import 'package:be_happy/domain/repositories/app_settings_repository.dart';
|
||||
import 'package:be_happy/domain/repositories/certificate_repository.dart';
|
||||
import 'package:be_happy/domain/repositories/notification_repository.dart';
|
||||
import 'package:be_happy/domain/repositories/payment_repository.dart'; // ← новый
|
||||
import 'package:be_happy/domain/repositories/pin_repository.dart';
|
||||
import 'package:be_happy/domain/repositories/profile_repository.dart';
|
||||
import 'package:be_happy/domain/repositories/scooter_repository.dart';
|
||||
import 'package:be_happy/domain/repositories/zone_repository.dart';
|
||||
import 'package:be_happy/domain/service/security_service.dart';
|
||||
import 'package:be_happy/domain/usecase/add_payment_card_usecase.dart'; // ← новый
|
||||
import 'package:be_happy/domain/usecase/get_certificates_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_scooter_order_route_history_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/is_pin_set_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/purchase_certificate_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/book_scooter_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/cancel_notification_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/create_pin_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_address_by_point_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_available_scooters_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_available_subscriptions_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_available_tariffs_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_available_zones_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_client_orders_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_map_settings_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_notifications_stream_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_payment_cards_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_pedestrian_routes_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_profile_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_scooter_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_subscription_by_id_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_subscription_by_id_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/login_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/logout_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/pay_ride_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/refresh_token_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/save_map_settings_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/update_profile_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/upload_profile_photo_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/verify_code_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/upload_scooter_photos_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/update_scooter_order_data_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/pay_scooter_order_with_photos_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/get_scooter_order_by_id_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/finish_ride_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/pause_ride_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/resume_ride_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/verify_pin_usecase.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/active_ride_bloc.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/add_card_bloc.dart'; // ← новый
|
||||
import 'package:be_happy/presentation/viewmodel/current_rides_bloc.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/map_settings_modal_bloc.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/payment_confirm_bloc.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/payment_method_sheet_bloc.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/payment_methods_bloc.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/pin_bloc.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/profile_bloc.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/scooter_detail_bloc.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/scooter_code_bloc.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/send_photo_bloc.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/splash_bloc.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/tariff_sheet_bloc.dart';
|
||||
import 'package:be_happy/domain/usecase/cancel_ride_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/start_ride_usecase.dart';
|
||||
import 'package:be_happy/domain/usecase/check_user_usecase.dart';
|
||||
import 'package:be_happy/presentation/viewmodel/reserved_ride_bloc.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../data/network/api_service.dart';
|
||||
import '../data/network/geocoding_remote_datasource.dart';
|
||||
import '../data/repositories/auth_repository_impl.dart';
|
||||
import '../data/repositories/news_repository_impl.dart';
|
||||
import '../data/repositories/pin_repository_impl.dart';
|
||||
import '../data/repositories/profile_repository_impl.dart';
|
||||
import '../data/service/news_api_service.dart';
|
||||
import '../domain/repositories/auth_repository.dart';
|
||||
import '../domain/repositories/news_repository.dart';
|
||||
import '../domain/service/device_info_service.dart';
|
||||
import '../domain/usecase/activate_subscription_usecase.dart';
|
||||
import '../domain/usecase/get_client_subscriptions_usecase.dart';
|
||||
import '../domain/usecase/get_news_by_id_usecase.dart';
|
||||
import '../domain/usecase/get_scooter_by_title_usecase.dart';
|
||||
import '../domain/usecase/get_scooter_order_history_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/map_bloc.dart';
|
||||
import '../presentation/viewmodel/news_bloc.dart';
|
||||
import '../presentation/viewmodel/order_history_bloc.dart';
|
||||
import '../presentation/viewmodel/scooter_detail_modal_bloc.dart';
|
||||
import '../presentation/viewmodel/subscription_list_bloc.dart';
|
||||
import '../presentation/viewmodel/verify_code_bloc.dart';
|
||||
|
||||
final getIt = GetIt.instance;
|
||||
|
||||
Future<void> setupDependencies() async {
|
||||
final sharedPreferences = await SharedPreferences.getInstance();
|
||||
final dio = Dio();
|
||||
dio.interceptors.add(LogInterceptor(responseBody: true, requestBody: true));
|
||||
// HTTP
|
||||
getIt.registerSingleton<http.Client>(http.Client());
|
||||
//SecureStorage
|
||||
getIt.registerSingleton<FlutterSecureStorage>(FlutterSecureStorage());
|
||||
|
||||
//SharedPrefs
|
||||
getIt.registerSingleton<SharedPreferences>(sharedPreferences);
|
||||
|
||||
// Service
|
||||
getIt.registerSingleton<SecurityService>(SecurityServiceImpl(getIt()));
|
||||
|
||||
getIt.registerLazySingleton(() => ApiService(getIt<SecurityService>(), dio));
|
||||
|
||||
getIt.registerSingleton<GeocodingRemoteDataSource>(
|
||||
GeocodingRemoteDataSource(),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<DeviceInfoService>(DeviceInfoServiceImpl());
|
||||
|
||||
getIt.registerSingleton<AppSettingsService>(AppSettingsService(getIt()));
|
||||
|
||||
getIt.registerLazySingleton<NewsApiService>(
|
||||
() => NewsApiService(getIt<ApiService>()),
|
||||
);
|
||||
|
||||
// Repository
|
||||
getIt.registerSingleton<AuthRepository>(
|
||||
AuthRepositoryImpl(getIt(), getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<PinRepository>(PinRepositoryImpl(getIt()));
|
||||
|
||||
getIt.registerSingleton<UserProfileRepository>(
|
||||
UserProfileRepositoryImpl(getIt()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<ScooterRepository>(ScooterRepositoryImpl(getIt()));
|
||||
|
||||
getIt.registerSingleton<ZoneRepository>(ZoneRepositoryImpl(getIt()));
|
||||
|
||||
getIt.registerSingleton<AppSettingsRepository>(
|
||||
AppSettingsRepositoryImpl(getIt()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<PaymentRepository>(
|
||||
PaymentRepositoryImpl(getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<CertificateRepository>(
|
||||
CertificateRepositoryImpl(getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerLazySingleton<NewsRepository>(
|
||||
() => NewsRepositoryImpl(getIt<NewsApiService>()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<NotificationRepository>(
|
||||
NotificationRepositoryImpl(getIt()),
|
||||
);
|
||||
|
||||
// Use Cases
|
||||
getIt.registerSingleton<LoginUseCase>(LoginUseCase(getIt()));
|
||||
|
||||
getIt.registerSingleton<LogoutUseCase>(LogoutUseCase(getIt(), getIt()));
|
||||
|
||||
getIt.registerSingleton<VerifyCodeUseCase>(VerifyCodeUseCase(getIt()));
|
||||
|
||||
getIt.registerSingleton<RefreshTokenUseCase>(RefreshTokenUseCase(getIt()));
|
||||
|
||||
getIt.registerSingleton<CreatePinUseCase>(CreatePinUseCase(getIt()));
|
||||
|
||||
getIt.registerSingleton<VerifyPinUseCase>(VerifyPinUseCase(getIt()));
|
||||
|
||||
getIt.registerSingleton<IsPinSetUsecase>(IsPinSetUsecase(getIt()));
|
||||
|
||||
getIt.registerSingleton<GetProfileUseCase>(GetProfileUseCase(getIt()));
|
||||
|
||||
getIt.registerSingleton<UpdateProfileUseCase>(UpdateProfileUseCase(getIt()));
|
||||
|
||||
getIt.registerSingleton<UploadProfilePhotoUsecase>(
|
||||
UploadProfilePhotoUsecase(getIt()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<GetAvailableScootersUsecase>(
|
||||
GetAvailableScootersUsecase(getIt()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<GetNewsByIdUsecase>(
|
||||
GetNewsByIdUsecase(getIt<NewsRepository>()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<GetScooterUsecase>(GetScooterUsecase(getIt()));
|
||||
getIt.registerSingleton<GetAvailableTariffsUsecase>(
|
||||
GetAvailableTariffsUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<GetAddressByPointUsecase>(
|
||||
GetAddressByPointUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<GetPedestrianRoutesUsecase>(
|
||||
GetPedestrianRoutesUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<GetScooterOrderRouteHistoryUsecase>(
|
||||
GetScooterOrderRouteHistoryUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<GetAvailableZonesUsecase>(
|
||||
GetAvailableZonesUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<GetMapSettingsUsecase>(
|
||||
GetMapSettingsUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<SaveMapSettingsUsecase>(
|
||||
SaveMapSettingsUsecase(getIt()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<AddPaymentCardUsecase>(
|
||||
AddPaymentCardUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<GetPaymentCardsUsecase>(
|
||||
GetPaymentCardsUsecase(getIt(), getIt()),
|
||||
);
|
||||
getIt.registerSingleton<SetMainPaymentCardUsecase>(
|
||||
SetMainPaymentCardUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<RemovePaymentCardUsecase>(
|
||||
RemovePaymentCardUsecase(getIt()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<GetCertificatesUsecase>(
|
||||
GetCertificatesUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<PurchaseCertificateUsecase>(
|
||||
PurchaseCertificateUsecase(getIt()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<GetClientOrdersUsecase>(
|
||||
GetClientOrdersUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<BookScooterUsecase>(BookScooterUsecase(getIt()));
|
||||
|
||||
getIt.registerSingleton<StartRideUsecase>(StartRideUsecase(getIt()));
|
||||
getIt.registerSingleton<CancelRideUsecase>(CancelRideUsecase(getIt()));
|
||||
|
||||
getIt.registerSingleton<UploadScooterPhotosUsecase>(
|
||||
UploadScooterPhotosUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<UpdateScooterOrderDataUsecase>(
|
||||
UpdateScooterOrderDataUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<PayScooterOrderWithPhotosUsecase>(
|
||||
PayScooterOrderWithPhotosUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<GetScooterOrderByIdUsecase>(
|
||||
GetScooterOrderByIdUsecase(getIt()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<FinishRideUsecase>(FinishRideUsecase(getIt()));
|
||||
getIt.registerSingleton<PauseRideUsecase>(PauseRideUsecase(getIt()));
|
||||
getIt.registerSingleton<ResumeRideUsecase>(ResumeRideUsecase(getIt()));
|
||||
getIt.registerSingleton<PayRideUsecase>(PayRideUsecase(getIt()));
|
||||
getIt.registerSingleton<GetAvailableSubscriptionsUsecase>(
|
||||
GetAvailableSubscriptionsUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<GetSubscriptionByIdUsecase>(
|
||||
GetSubscriptionByIdUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<ActivateSubscriptionUsecase>(
|
||||
ActivateSubscriptionUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<GetClientSubscriptionsUsecase>(
|
||||
GetClientSubscriptionsUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<GetScooterByTitleUsecase>(
|
||||
GetScooterByTitleUsecase(getIt()),
|
||||
);
|
||||
|
||||
// Blocs
|
||||
getIt.registerLazySingleton<SplashBloc>(() => SplashBloc(getIt()));
|
||||
|
||||
getIt.registerFactory<PhoneAuthBloc>(() => PhoneAuthBloc(getIt()));
|
||||
|
||||
getIt.registerFactory<VerifyCodeBloc>(() => VerifyCodeBloc(getIt()));
|
||||
|
||||
getIt.registerFactory<ProfileBloc>(() => ProfileBloc(getIt(), getIt(), getIt()));
|
||||
|
||||
getIt.registerFactory<EditProfileBloc>(
|
||||
() => EditProfileBloc(getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<MapBloc>(
|
||||
() => MapBloc(
|
||||
getIt(),
|
||||
getIt(),
|
||||
getIt(),
|
||||
getIt(),
|
||||
getIt(),
|
||||
getIt(),
|
||||
getIt(),
|
||||
getIt(),
|
||||
),
|
||||
);
|
||||
|
||||
getIt.registerFactory<ScooterDetailBloc>(() => ScooterDetailBloc(getIt()));
|
||||
|
||||
getIt.registerFactory<MapSettingsModalBloc>(
|
||||
() => MapSettingsModalBloc(getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<AddCardBloc>(() => AddCardBloc(getIt()));
|
||||
|
||||
|
||||
getIt.registerFactory<PaymentMethodSheetBloc>(
|
||||
() => PaymentMethodSheetBloc(getIt()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<CurrentRidesBloc>(() => CurrentRidesBloc(getIt()));
|
||||
|
||||
getIt.registerFactory<ActiveRideBloc>(
|
||||
() => ActiveRideBloc(getIt(), getIt(), getIt(), getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<ReservedRideBloc>(
|
||||
() => ReservedRideBloc(getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<NewsBloc>(() => NewsBloc(getIt<NewsRepository>()));
|
||||
|
||||
|
||||
getIt.registerFactory<SendPhotoBloc>(() => SendPhotoBloc(getIt(), getIt()));
|
||||
|
||||
getIt.registerFactory<SubscriptionListBloc>(
|
||||
() => SubscriptionListBloc(
|
||||
getAvailableSubscriptionsUsecase: getIt(),
|
||||
getClientSubscriptionsUsecase: getIt(),
|
||||
),
|
||||
);
|
||||
|
||||
// UseCase
|
||||
getIt.registerSingleton<GetScooterOrderHistoryUsecase>(
|
||||
GetScooterOrderHistoryUsecase(getIt<ScooterRepository>()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<CheckUserUseCase>(
|
||||
CheckUserUseCase(getIt<UserProfileRepository>()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<GetNotificationsStreamUseCase>(
|
||||
GetNotificationsStreamUseCase(getIt<NotificationRepository>()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<CancelNotificationUseCase>(
|
||||
CancelNotificationUseCase(getIt<NotificationRepository>()),
|
||||
);
|
||||
|
||||
// Bloc
|
||||
getIt.registerFactory<OrderHistoryBloc>(
|
||||
() => OrderHistoryBloc(getIt<GetScooterOrderHistoryUsecase>()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<ScooterCodeBloc>(
|
||||
() => ScooterCodeBloc(getScooterByTitleUsecase: getIt<GetScooterByTitleUsecase>()),
|
||||
);
|
||||
}
|
||||
50
lib/domain/entities/active_scooter_order.dart
Normal file
50
lib/domain/entities/active_scooter_order.dart
Normal file
@@ -0,0 +1,50 @@
|
||||
import 'scooter.dart';
|
||||
|
||||
class ActiveScooterOrder {
|
||||
final int orderId;
|
||||
final int scooterId;
|
||||
final double latitude;
|
||||
final double longitude;
|
||||
final double mileage;
|
||||
final double speed;
|
||||
final double price;
|
||||
final double time;
|
||||
final bool zone;
|
||||
|
||||
ActiveScooterOrder({
|
||||
required this.orderId,
|
||||
required this.scooterId,
|
||||
required this.latitude,
|
||||
required this.longitude,
|
||||
required this.mileage,
|
||||
required this.speed,
|
||||
required this.price,
|
||||
required this.time,
|
||||
required this.zone,
|
||||
});
|
||||
|
||||
factory ActiveScooterOrder.fromJson(Map<String, dynamic> json) {
|
||||
return ActiveScooterOrder(
|
||||
orderId: json['orderId'] ?? 0,
|
||||
scooterId: json['scooterId'] ?? 0,
|
||||
latitude: (json['latitude'] ?? 0).toDouble(),
|
||||
longitude: (json['longitude'] ?? 0).toDouble(),
|
||||
mileage: (json['mileage'] ?? 0).toDouble(),
|
||||
speed: (json['speed'] ?? 0).toDouble(),
|
||||
price: (json['price'] ?? 0).toDouble(),
|
||||
time: (json['time'] ?? 0.0).toDouble(),
|
||||
zone: json['zone'],
|
||||
);
|
||||
}
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'orderId': orderId,
|
||||
'scooterId': scooterId,
|
||||
'latitude': latitude,
|
||||
'longitude': longitude,
|
||||
'mileage': mileage,
|
||||
'speed': speed,
|
||||
'price': price,
|
||||
};
|
||||
}
|
||||
}
|
||||
94
lib/domain/entities/certificate.dart
Normal file
94
lib/domain/entities/certificate.dart
Normal file
@@ -0,0 +1,94 @@
|
||||
class Currency {
|
||||
final int id;
|
||||
final String title;
|
||||
final String currency;
|
||||
final String code;
|
||||
final bool isBase;
|
||||
final int denomination;
|
||||
final double exchangeRate;
|
||||
final String formatString;
|
||||
final String floatSeparator;
|
||||
final int decimals;
|
||||
final bool isHideZero;
|
||||
|
||||
Currency({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.currency,
|
||||
required this.code,
|
||||
required this.isBase,
|
||||
required this.denomination,
|
||||
required this.exchangeRate,
|
||||
required this.formatString,
|
||||
required this.floatSeparator,
|
||||
required this.decimals,
|
||||
required this.isHideZero,
|
||||
});
|
||||
|
||||
factory Currency.fromJson(Map<String, dynamic> json) {
|
||||
return Currency(
|
||||
id: json['id'] as int,
|
||||
title: json['title'] as String,
|
||||
currency: json['currency'] as String,
|
||||
code: json['code'] as String,
|
||||
isBase: json['isBase'] as bool,
|
||||
denomination: json['denomination'] as int,
|
||||
exchangeRate: (json['exchangeRate'] as num).toDouble(),
|
||||
formatString: json['formatString'] as String,
|
||||
floatSeparator: json['floatSeparator'] as String,
|
||||
decimals: json['decimals'] as int,
|
||||
isHideZero: json['isHideZero'] as bool,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Certificate {
|
||||
final int id;
|
||||
final String title;
|
||||
final String? description;
|
||||
final double price;
|
||||
final int currencyId;
|
||||
final int value;
|
||||
final double discount;
|
||||
final DateTime createdAt;
|
||||
final DateTime updatedAt;
|
||||
final int sort;
|
||||
final bool isActive;
|
||||
final Currency? currency;
|
||||
final String? pricePrint;
|
||||
|
||||
Certificate({
|
||||
required this.id,
|
||||
required this.title,
|
||||
this.description,
|
||||
required this.price,
|
||||
required this.currencyId,
|
||||
required this.value,
|
||||
required this.discount,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.sort,
|
||||
required this.isActive,
|
||||
this.currency,
|
||||
this.pricePrint,
|
||||
});
|
||||
|
||||
factory Certificate.fromJson(Map<String, dynamic> json) {
|
||||
return Certificate(
|
||||
id: json['id'] as int,
|
||||
title: json['title'] as String,
|
||||
description: json['description'] as String?,
|
||||
price: (json['price'] as num).toDouble(),
|
||||
currencyId: json['currencyId'] as int,
|
||||
value: json['value'] as int,
|
||||
discount: (json['discount'] as num).toDouble(),
|
||||
createdAt: DateTime.parse(json['createdAt'] as String),
|
||||
updatedAt: DateTime.parse(json['updatedAt'] as String),
|
||||
sort: json['sort'] as int,
|
||||
isActive: json['isActive'] as bool,
|
||||
currency: json['currency'] != null ? Currency.fromJson(json['currency']) : null,
|
||||
pricePrint: json['pricePrint'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
58
lib/domain/entities/client_notification.dart
Normal file
58
lib/domain/entities/client_notification.dart
Normal file
@@ -0,0 +1,58 @@
|
||||
enum NotificationType {
|
||||
info,
|
||||
attention,
|
||||
warning,
|
||||
}
|
||||
|
||||
enum NotificationCategory {
|
||||
auth,
|
||||
zone,
|
||||
payment,
|
||||
companyInfo,
|
||||
adminInfo,
|
||||
scooter,
|
||||
}
|
||||
|
||||
class ClientNotification {
|
||||
final int id;
|
||||
final String content;
|
||||
final int clientId;
|
||||
final NotificationType type;
|
||||
final NotificationCategory category;
|
||||
final DateTime createdAt;
|
||||
final DateTime? canceledAt;
|
||||
final DateTime? readAt;
|
||||
|
||||
ClientNotification({
|
||||
required this.id,
|
||||
required this.content,
|
||||
required this.clientId,
|
||||
required this.type,
|
||||
required this.category,
|
||||
required this.createdAt,
|
||||
this.canceledAt,
|
||||
this.readAt,
|
||||
});
|
||||
|
||||
ClientNotification copyWith({
|
||||
int? id,
|
||||
String? content,
|
||||
int? clientId,
|
||||
NotificationType? type,
|
||||
NotificationCategory? category,
|
||||
DateTime? createdAt,
|
||||
DateTime? canceledAt,
|
||||
DateTime? readAt,
|
||||
}) {
|
||||
return ClientNotification(
|
||||
id: id ?? this.id,
|
||||
content: content ?? this.content,
|
||||
clientId: clientId ?? this.clientId,
|
||||
type: type ?? this.type,
|
||||
category: category ?? this.category,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
canceledAt: canceledAt ?? this.canceledAt,
|
||||
readAt: readAt ?? this.readAt,
|
||||
);
|
||||
}
|
||||
}
|
||||
15
lib/domain/entities/map_settings.dart
Normal file
15
lib/domain/entities/map_settings.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
class MapSettings {
|
||||
final bool all_placemarks;
|
||||
final bool all_zones;
|
||||
final bool parking_zones;
|
||||
final bool restricted_parking_zones;
|
||||
final bool restricted_driving_zones;
|
||||
|
||||
MapSettings({
|
||||
required this.all_placemarks,
|
||||
required this.all_zones,
|
||||
required this.parking_zones,
|
||||
required this.restricted_parking_zones,
|
||||
required this.restricted_driving_zones,
|
||||
});
|
||||
}
|
||||
62
lib/domain/entities/news.dart
Normal file
62
lib/domain/entities/news.dart
Normal file
@@ -0,0 +1,62 @@
|
||||
class NewsEntity {
|
||||
final int id;
|
||||
final String title;
|
||||
final String previewText;
|
||||
final String text;
|
||||
final DateTime createdAt;
|
||||
final DateTime publishedAt;
|
||||
final bool isActive;
|
||||
final String? imageUrl;
|
||||
|
||||
final String? textJson;
|
||||
final int? userId;
|
||||
final int? pictureId;
|
||||
final dynamic user;
|
||||
final dynamic picture;
|
||||
|
||||
NewsEntity({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.previewText,
|
||||
required this.text,
|
||||
required this.createdAt,
|
||||
required this.publishedAt,
|
||||
required this.isActive,
|
||||
this.imageUrl,
|
||||
|
||||
this.textJson,
|
||||
this.userId,
|
||||
this.pictureId,
|
||||
this.user,
|
||||
this.picture,
|
||||
});
|
||||
|
||||
factory NewsEntity.fromJson(Map<String, dynamic> json) {
|
||||
DateTime _parseDate(String? dateStr) {
|
||||
try {
|
||||
return dateStr != null ? DateTime.parse(dateStr) : DateTime.now();
|
||||
} catch (_) {
|
||||
return DateTime.now();
|
||||
}
|
||||
}
|
||||
|
||||
return NewsEntity(
|
||||
id: json['id'] ?? 0,
|
||||
title: json['title'] ?? '',
|
||||
previewText: json['previewText'] ?? '',
|
||||
text: json['text'] ?? '',
|
||||
createdAt: _parseDate(json['createdAt']),
|
||||
publishedAt: _parseDate(json['publishedAt']),
|
||||
isActive: json['isActive'] ?? false,
|
||||
imageUrl: json['picture'] != null
|
||||
? 'https://sharing-api.sparkit.by/${json['picture']['path']}'
|
||||
: null,
|
||||
|
||||
textJson: json['textJson'],
|
||||
userId: json['userId'],
|
||||
pictureId: json['pictureId'],
|
||||
user: json['user'],
|
||||
picture: json['picture'],
|
||||
);
|
||||
}
|
||||
}
|
||||
19
lib/domain/entities/pagination.dart
Normal file
19
lib/domain/entities/pagination.dart
Normal file
@@ -0,0 +1,19 @@
|
||||
class Pagination {
|
||||
final int total;
|
||||
final int currentPage;
|
||||
final int lastPage;
|
||||
|
||||
Pagination({
|
||||
required this.total,
|
||||
required this.currentPage,
|
||||
required this.lastPage,
|
||||
});
|
||||
|
||||
factory Pagination.fromJson(Map<String, dynamic> json) {
|
||||
return Pagination(
|
||||
total: json['total'] ?? 0,
|
||||
currentPage: json['currentPage'] ?? 0,
|
||||
lastPage: json['lastPage'] ?? 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
43
lib/domain/entities/payment_card.dart
Normal file
43
lib/domain/entities/payment_card.dart
Normal file
@@ -0,0 +1,43 @@
|
||||
class PaymentCard {
|
||||
final int id;
|
||||
final int clientId;
|
||||
final int expirationMonth;
|
||||
final int expirationYear;
|
||||
final String cardHolder;
|
||||
final String cardLastNumber;
|
||||
final bool isMain;
|
||||
final String type;
|
||||
|
||||
PaymentCard({
|
||||
required this.id,
|
||||
required this.clientId,
|
||||
required this.expirationMonth,
|
||||
required this.expirationYear,
|
||||
required this.cardHolder,
|
||||
required this.cardLastNumber,
|
||||
required this.isMain,
|
||||
required this.type,
|
||||
});
|
||||
|
||||
PaymentCard copyWith({
|
||||
int? id,
|
||||
int? clientId,
|
||||
int? expirationMonth,
|
||||
int? expirationYear,
|
||||
String? cardHolder,
|
||||
String? cardLastNumber,
|
||||
bool? isMain,
|
||||
String? type,
|
||||
}) {
|
||||
return PaymentCard(
|
||||
id: id ?? this.id,
|
||||
clientId: clientId ?? this.clientId,
|
||||
expirationMonth: expirationMonth ?? this.expirationMonth,
|
||||
expirationYear: expirationYear ?? this.expirationYear,
|
||||
cardHolder: cardHolder ?? this.cardHolder,
|
||||
cardLastNumber: cardLastNumber ?? this.cardLastNumber,
|
||||
isMain: isMain ?? this.isMain,
|
||||
type: type ?? this.type,
|
||||
);
|
||||
}
|
||||
}
|
||||
12
lib/domain/entities/point.dart
Normal file
12
lib/domain/entities/point.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
class Point {
|
||||
final double latitude;
|
||||
final double longitude;
|
||||
|
||||
Point(this.latitude, this.longitude);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Point{latitude: $latitude, longitude: $longitude}';
|
||||
}
|
||||
}
|
||||
50
lib/domain/entities/scooter.dart
Normal file
50
lib/domain/entities/scooter.dart
Normal file
@@ -0,0 +1,50 @@
|
||||
|
||||
class Scooter {
|
||||
final int id;
|
||||
final String title;
|
||||
final String status;
|
||||
final double latitude;
|
||||
final double longitude;
|
||||
final int batteryLevel;
|
||||
final bool isOnline;
|
||||
final int maxSpeed;
|
||||
final String number;
|
||||
double? distance;
|
||||
double? timeToTravel;
|
||||
|
||||
Scooter({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.status,
|
||||
required this.latitude,
|
||||
required this.longitude,
|
||||
required this.batteryLevel,
|
||||
required this.isOnline,
|
||||
required this.maxSpeed,
|
||||
required this.number,
|
||||
this.distance,
|
||||
this.timeToTravel,
|
||||
});
|
||||
|
||||
factory Scooter.fromJson(Map<String, dynamic> json) {
|
||||
final scooterDetail = json['scooterDetail'] as Map<String, dynamic>? ?? {};
|
||||
final model = json['model'] as Map<String, dynamic>? ?? {};
|
||||
|
||||
return Scooter(
|
||||
id: json['id'] ?? 0,
|
||||
title: json['title'] ?? 'Unknown',
|
||||
status: json['status'] ?? 'Unavailable',
|
||||
latitude: (scooterDetail['latitude'] as num?)?.toDouble() ?? 0.0,
|
||||
longitude: (scooterDetail['longitude'] as num?)?.toDouble() ?? 0.0,
|
||||
batteryLevel: (scooterDetail['batteryLevel'] as num?)?.toInt() ?? 0,
|
||||
isOnline: scooterDetail['isOnline'] ?? false,
|
||||
maxSpeed: (json['maxSpeed'] as num?)?.toInt() ?? 25,
|
||||
number: json['title'] ?? 'Unknown',
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Scooter{id: $id, title: $title}';
|
||||
}
|
||||
}
|
||||
143
lib/domain/entities/scooter_order.dart
Normal file
143
lib/domain/entities/scooter_order.dart
Normal file
@@ -0,0 +1,143 @@
|
||||
import 'scooter.dart';
|
||||
|
||||
class ScooterOrder {
|
||||
final int id;
|
||||
final int scooterId;
|
||||
final Scooter? scooter;
|
||||
final int? planId;
|
||||
final ScooterPlan? plan;
|
||||
final int clientId;
|
||||
final int? subscriptionId;
|
||||
final int? cardId;
|
||||
final bool isBalance;
|
||||
final int decimals;
|
||||
final bool isInsurance;
|
||||
final double? insurancePrice;
|
||||
final String? insurancePricePrint;
|
||||
final double? holdPrice;
|
||||
final String? holdPricePrint;
|
||||
final double? totalPrice;
|
||||
final String? totalPricePrint;
|
||||
final int? currencyId;
|
||||
final String status;
|
||||
final DateTime createdAt;
|
||||
final DateTime? updatedAt;
|
||||
final DateTime? startAt;
|
||||
final DateTime? finishAt;
|
||||
final DateTime? expiresAt;
|
||||
final DateTime? cancelAt;
|
||||
final String? cancelDescription;
|
||||
final double mileage; //эту
|
||||
final double avgSpeed; //эту и снизу еще 4 есть
|
||||
|
||||
ScooterOrder({
|
||||
required this.id,
|
||||
required this.scooterId,
|
||||
this.scooter,
|
||||
this.planId,
|
||||
this.plan,
|
||||
required this.clientId,
|
||||
this.subscriptionId,
|
||||
this.cardId,
|
||||
required this.isBalance,
|
||||
required this.decimals,
|
||||
required this.isInsurance,
|
||||
this.insurancePrice,
|
||||
this.insurancePricePrint,
|
||||
this.holdPrice,
|
||||
this.holdPricePrint,
|
||||
this.totalPrice,
|
||||
this.totalPricePrint,
|
||||
this.currencyId,
|
||||
required this.status,
|
||||
required this.createdAt,
|
||||
this.updatedAt,
|
||||
this.startAt,
|
||||
this.finishAt,
|
||||
this.expiresAt,
|
||||
this.cancelAt,
|
||||
this.cancelDescription,
|
||||
required this.mileage, //эту
|
||||
required this.avgSpeed, //эту и снизу еще 2 есть
|
||||
});
|
||||
|
||||
factory ScooterOrder.fromJson(Map<String, dynamic> json) {
|
||||
return ScooterOrder(
|
||||
id: json['id'] ?? 0,
|
||||
scooterId: json['scooterId'] ?? 0,
|
||||
scooter: json['scooter'] != null ? Scooter.fromJson(json['scooter']) : null,
|
||||
planId: json['planId'],
|
||||
plan: json['plan'] != null ? ScooterPlan.fromJson(json['plan']) : null,
|
||||
clientId: json['clientId'] ?? 0,
|
||||
subscriptionId: json['subscriptionId'],
|
||||
cardId: json['cardId'],
|
||||
isBalance: json['isBalance'] ?? false,
|
||||
decimals: json['decimals'] ?? 0,
|
||||
isInsurance: json['isInsurance'] ?? false,
|
||||
insurancePrice: (json['insurancePrice'] as num?)?.toDouble(),
|
||||
insurancePricePrint: json['insurancePricePrint'],
|
||||
holdPrice: (json['holdPrice'] as num?)?.toDouble(),
|
||||
holdPricePrint: json['holdPricePrint'],
|
||||
totalPrice: (json['totalPrice'] as num?)?.toDouble(),
|
||||
totalPricePrint: json['totalPricePrint'],
|
||||
currencyId: json['currencyId'],
|
||||
status: json['status'] ?? '',
|
||||
createdAt: json['createdAt'] != null
|
||||
? DateTime.parse(json['createdAt'])
|
||||
: DateTime.now(),
|
||||
updatedAt: json['updatedAt'] != null
|
||||
? DateTime.parse(json['updatedAt'])
|
||||
: null,
|
||||
startAt: json['startAt'] != null
|
||||
? DateTime.parse(json['startAt'])
|
||||
: null,
|
||||
finishAt: json['finishAt'] != null
|
||||
? DateTime.parse(json['finishAt'])
|
||||
: null,
|
||||
expiresAt: json['expiresAt'] != null
|
||||
? DateTime.parse(json['expiresAt'])
|
||||
: null,
|
||||
cancelAt: json['cancelAt'] != null
|
||||
? DateTime.parse(json['cancelAt'])
|
||||
: null,
|
||||
cancelDescription: json['cancelDescription'],
|
||||
mileage: (json['mileage'] as num?)?.toDouble() ?? 0.0, //эту
|
||||
avgSpeed: (json['avgSpeed'] as num?)?.toDouble() ?? 0.0, //эту
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'scooterId': scooterId,
|
||||
'planId': planId,
|
||||
'subscriptionId': subscriptionId,
|
||||
'cardId': cardId,
|
||||
'isBalance': isBalance,
|
||||
'isInsurance': isInsurance,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class ScooterPlan {
|
||||
final int id;
|
||||
final String title;
|
||||
final double price;
|
||||
final String? description;
|
||||
|
||||
ScooterPlan({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.price,
|
||||
this.description,
|
||||
});
|
||||
|
||||
factory ScooterPlan.fromJson(Map<String, dynamic> json) {
|
||||
return ScooterPlan(
|
||||
id: json['id'] ?? 0,
|
||||
title: json['title'] ?? '',
|
||||
price: (json['price'] as num?)?.toDouble() ?? 0.0,
|
||||
description: json['description'],
|
||||
);
|
||||
}
|
||||
}
|
||||
59
lib/domain/entities/subscription.dart
Normal file
59
lib/domain/entities/subscription.dart
Normal file
@@ -0,0 +1,59 @@
|
||||
|
||||
import 'package:be_happy/domain/entities/subscription_period.dart';
|
||||
|
||||
class Subscription {
|
||||
final int id;
|
||||
final String title;
|
||||
final String shortDescription;
|
||||
final String fullDescription;
|
||||
final int planId;
|
||||
final bool isActive;
|
||||
final String currency;
|
||||
final DateTime? activeFrom;
|
||||
final DateTime? activeTo;
|
||||
final DateTime createdAt;
|
||||
final DateTime updatedAt;
|
||||
final List<SubscriptionPeriod> options;
|
||||
|
||||
|
||||
Subscription({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.shortDescription,
|
||||
required this.fullDescription,
|
||||
required this.planId,
|
||||
required this.isActive,
|
||||
required this.currency,
|
||||
this.activeFrom,
|
||||
this.activeTo,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.options,
|
||||
});
|
||||
|
||||
factory Subscription.fromJson(Map<String, dynamic> json) {
|
||||
final currencyData = json['currency'] as Map<String, dynamic>? ?? {};
|
||||
final optionsData = json['options'] as List<dynamic>? ?? [];
|
||||
|
||||
|
||||
return Subscription(
|
||||
id: json['id'] ?? 0,
|
||||
title: json['title'] ?? '',
|
||||
shortDescription: json['shortDescription'] ?? '',
|
||||
fullDescription: json['fullDescription'] ?? '',
|
||||
planId: json['planId'] ?? 0,
|
||||
isActive: json['isActive'] ?? false,
|
||||
currency: currencyData['currency'] ?? 'BYN',
|
||||
activeFrom: json['activeFrom'] != null ? DateTime.parse(json['activeFrom']) : null,
|
||||
activeTo: json['activeTo'] != null ? DateTime.parse(json['activeTo']) : null,
|
||||
createdAt: json['createdAt'] != null ? DateTime.parse(json['createdAt']) : DateTime.now(),
|
||||
updatedAt: json['updatedAt'] != null ? DateTime.parse(json['updatedAt']) : DateTime.now(),
|
||||
options: optionsData.map((e) => SubscriptionPeriod.fromJson(e as Map<String, dynamic>)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Subscription{id: $id, title: $title, isActive: $isActive}';
|
||||
}
|
||||
}
|
||||
33
lib/domain/entities/subscription_period.dart
Normal file
33
lib/domain/entities/subscription_period.dart
Normal file
@@ -0,0 +1,33 @@
|
||||
class SubscriptionPeriod {
|
||||
final int id;
|
||||
final int subscriptionId;
|
||||
final int days;
|
||||
final String title;
|
||||
final double price;
|
||||
final String pricePrint;
|
||||
|
||||
SubscriptionPeriod({
|
||||
required this.id,
|
||||
required this.subscriptionId,
|
||||
required this.days,
|
||||
required this.title,
|
||||
required this.price,
|
||||
required this.pricePrint,
|
||||
});
|
||||
|
||||
factory SubscriptionPeriod.fromJson(Map<String, dynamic> json) {
|
||||
return SubscriptionPeriod(
|
||||
id: json['id'] ?? 0,
|
||||
subscriptionId: json['subscriptionId'] ?? 0,
|
||||
days: json['days'] ?? 0,
|
||||
title: json['title'] ?? '',
|
||||
price: (json['price'] ?? 0).toDouble(),
|
||||
pricePrint: json['pricePrint'] ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SubscriptionPeriod{id: $id, title: $title, days: $days, price: $price}';
|
||||
}
|
||||
}
|
||||
51
lib/domain/entities/tariff.dart
Normal file
51
lib/domain/entities/tariff.dart
Normal file
@@ -0,0 +1,51 @@
|
||||
class Tariff {
|
||||
final int id;
|
||||
final String title;
|
||||
final String description;
|
||||
final bool isActive;
|
||||
final String currency;
|
||||
final double holdPrice; // Старт / бронь
|
||||
final double drivePrice; // Цена минуты
|
||||
final double pausePrice; // Пауза
|
||||
final double startPrice; // Старт цена
|
||||
final double cashback; // Процент кэшбэка
|
||||
final double insurance; // Страховка
|
||||
|
||||
Tariff({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.description,
|
||||
required this.isActive,
|
||||
required this.currency,
|
||||
required this.holdPrice,
|
||||
required this.drivePrice,
|
||||
required this.pausePrice,
|
||||
required this.startPrice,
|
||||
required this.cashback,
|
||||
required this.insurance,
|
||||
});
|
||||
|
||||
factory Tariff.fromJson(Map<String, dynamic> json) {
|
||||
final planPrice = json['planPrice'] as Map<String, dynamic>? ?? {};
|
||||
final currency = json['currency'] as Map<String, dynamic>? ?? {};
|
||||
|
||||
return Tariff(
|
||||
id: json['id'] ?? 0,
|
||||
title: json['title'] ?? 'Unknown',
|
||||
description: json['description'] ?? '',
|
||||
isActive: json['isActive'] ?? false,
|
||||
currency: currency['currency'] ?? 'BYN',
|
||||
holdPrice: (planPrice['hold'] as num?)?.toDouble() ?? 0.0,
|
||||
drivePrice: (planPrice['drive'] as num?)?.toDouble() ?? 0.0,
|
||||
pausePrice: (planPrice['pause'] as num?)?.toDouble() ?? 0.0,
|
||||
startPrice: (planPrice['start'] as num?)?.toDouble() ?? 0.0,
|
||||
cashback: (planPrice['cashback'] as num?)?.toDouble() ?? 0.0,
|
||||
insurance: (planPrice['insurance'] as num?)?.toDouble() ?? 0.0,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Tariff{id: $id, title: $title, isActive: $isActive}';
|
||||
}
|
||||
}
|
||||
17
lib/domain/entities/top_up_tariff.dart
Normal file
17
lib/domain/entities/top_up_tariff.dart
Normal file
@@ -0,0 +1,17 @@
|
||||
class TopUpTariff {
|
||||
final int id;
|
||||
final int points;
|
||||
final double price;
|
||||
final double? discountPercent;
|
||||
|
||||
TopUpTariff({
|
||||
required this.id,
|
||||
required this.points,
|
||||
required this.price,
|
||||
this.discountPercent,
|
||||
});
|
||||
|
||||
double get finalPrice => discountPercent != null
|
||||
? price * (1 - discountPercent! / 100)
|
||||
: price;
|
||||
}
|
||||
9
lib/domain/entities/user_auth_data.dart
Normal file
9
lib/domain/entities/user_auth_data.dart
Normal file
@@ -0,0 +1,9 @@
|
||||
class UserAuthData {
|
||||
final String accessToken;
|
||||
final String refreshToken;
|
||||
|
||||
UserAuthData({
|
||||
required this.accessToken,
|
||||
required this.refreshToken,
|
||||
});
|
||||
}
|
||||
23
lib/domain/entities/user_check_flags.dart
Normal file
23
lib/domain/entities/user_check_flags.dart
Normal file
@@ -0,0 +1,23 @@
|
||||
class UserCheckFlags {
|
||||
final bool hasFine;
|
||||
final bool hasUnpaidOrder;
|
||||
final bool hasCard;
|
||||
|
||||
const UserCheckFlags({
|
||||
required this.hasFine,
|
||||
required this.hasUnpaidOrder,
|
||||
required this.hasCard,
|
||||
});
|
||||
|
||||
UserCheckFlags copyWith({
|
||||
bool? hasFine,
|
||||
bool? hasUnpaidOrder,
|
||||
bool? hasCard,
|
||||
}) {
|
||||
return UserCheckFlags(
|
||||
hasFine: hasFine ?? this.hasFine,
|
||||
hasUnpaidOrder: hasUnpaidOrder ?? this.hasUnpaidOrder,
|
||||
hasCard: hasCard ?? this.hasCard,
|
||||
);
|
||||
}
|
||||
}
|
||||
38
lib/domain/entities/user_profile.dart
Normal file
38
lib/domain/entities/user_profile.dart
Normal file
@@ -0,0 +1,38 @@
|
||||
class UserProfile {
|
||||
String name;
|
||||
String birthDate;
|
||||
String phone;
|
||||
String email;
|
||||
int? balance;
|
||||
int? avatarId;
|
||||
String? avatarUrl;
|
||||
|
||||
UserProfile({
|
||||
required this.name,
|
||||
required this.birthDate,
|
||||
required this.phone,
|
||||
required this.email,
|
||||
this.balance,
|
||||
this.avatarId,
|
||||
this.avatarUrl,
|
||||
});
|
||||
|
||||
UserProfile copyWith({
|
||||
String? name,
|
||||
String? birthDate,
|
||||
String? email,
|
||||
int? balance,
|
||||
int? avatarId,
|
||||
String? avatarUrl,
|
||||
}) {
|
||||
return UserProfile(
|
||||
name: name ?? this.name,
|
||||
birthDate: birthDate ?? this.birthDate,
|
||||
phone: phone, // телефон не меняется
|
||||
email: email ?? this.email,
|
||||
balance: balance ?? this.balance,
|
||||
avatarId: avatarId ?? this.avatarId,
|
||||
avatarUrl: avatarUrl ?? this.avatarUrl,
|
||||
);
|
||||
}
|
||||
}
|
||||
74
lib/domain/entities/zone.dart
Normal file
74
lib/domain/entities/zone.dart
Normal file
@@ -0,0 +1,74 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:be_happy/domain/entities/point.dart';
|
||||
|
||||
class Zone {
|
||||
final int id;
|
||||
final String title;
|
||||
final String description;
|
||||
final String type;
|
||||
final bool isActive;
|
||||
final String shapeType;
|
||||
final List<Point> points;
|
||||
final String speedLimit;
|
||||
|
||||
Zone({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.description,
|
||||
required this.type,
|
||||
required this.isActive,
|
||||
required this.shapeType,
|
||||
required this.points,
|
||||
required this.speedLimit,
|
||||
});
|
||||
|
||||
factory Zone.fromJson(Map<String, dynamic> json) {
|
||||
final zoneCoordinates = json['coordinates'] as Map<String, dynamic>? ?? {};
|
||||
final String coordsString = zoneCoordinates['coordinates'] ?? '[]';
|
||||
final String shapeType = zoneCoordinates['type'] ?? 'Polygon';
|
||||
|
||||
List<Point> points = [];
|
||||
|
||||
try {
|
||||
final dynamic decoded = jsonDecode(coordsString);
|
||||
|
||||
if (decoded is List && decoded.isNotEmpty) {
|
||||
List<dynamic> targetList = [];
|
||||
|
||||
if (shapeType == 'Polygon') {
|
||||
// У полигона структура [[[lat, lon], ...]] -> уходим на 1 уровень вглубь
|
||||
targetList = decoded[0] as List<dynamic>;
|
||||
} else {
|
||||
// У LineString структура [[lat, lon], ...] -> используем как есть
|
||||
targetList = decoded;
|
||||
}
|
||||
|
||||
points = targetList.map((item) {
|
||||
final List<dynamic> coords = item as List<dynamic>;
|
||||
return Point(
|
||||
(coords[1] as num).toDouble(),
|
||||
(coords[0] as num).toDouble(),
|
||||
);
|
||||
}).toList();
|
||||
}
|
||||
} catch (e) {
|
||||
print("PARSE ERROR for Zone ID ${json['id']}: $e");
|
||||
}
|
||||
|
||||
return Zone(
|
||||
id: json['id'] ?? 0,
|
||||
title: json['title'] ?? 'Unknown',
|
||||
description: json['description'] ?? '',
|
||||
type: json['type'] ?? '',
|
||||
isActive: json['isActive'] ?? false,
|
||||
speedLimit: json['speedLimit'] ?? '',
|
||||
shapeType: shapeType,
|
||||
points: points,
|
||||
);
|
||||
}
|
||||
@override
|
||||
String toString() {
|
||||
return 'Zone{id: $id, title: $title, type: $type, points: $points}';
|
||||
}
|
||||
}
|
||||
7
lib/domain/repositories/app_settings_repository.dart
Normal file
7
lib/domain/repositories/app_settings_repository.dart
Normal file
@@ -0,0 +1,7 @@
|
||||
import 'package:be_happy/domain/entities/map_settings.dart';
|
||||
|
||||
abstract class AppSettingsRepository {
|
||||
|
||||
Future<MapSettings> getMapSettings();
|
||||
Future<void> saveMapSettings(MapSettings settings);
|
||||
}
|
||||
14
lib/domain/repositories/auth_repository.dart
Normal file
14
lib/domain/repositories/auth_repository.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
import 'dart:ffi';
|
||||
|
||||
import '../../core/result.dart';
|
||||
import '../entities/user_auth_data.dart';
|
||||
|
||||
abstract class AuthRepository {
|
||||
Future<String> login(String phone);
|
||||
|
||||
Future<Result<void>> verifyCode(String code, String token);
|
||||
|
||||
Future<UserAuthData> refreshToken();
|
||||
|
||||
Future<void> logout();
|
||||
}
|
||||
11
lib/domain/repositories/certificate_repository.dart
Normal file
11
lib/domain/repositories/certificate_repository.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
import '../../core/result.dart';
|
||||
import '../entities/certificate.dart';
|
||||
|
||||
abstract class CertificateRepository {
|
||||
Future<Result<List<Certificate>>> getCertificates();
|
||||
|
||||
Future<Result<Map<String, dynamic>>> purchaseCertificate({
|
||||
required int certificateId,
|
||||
required int cardId,
|
||||
});
|
||||
}
|
||||
3
lib/domain/repositories/launch_repository.dart
Normal file
3
lib/domain/repositories/launch_repository.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
abstract class LaunchRepository {
|
||||
Future<bool> isFirstLaunch();
|
||||
}
|
||||
6
lib/domain/repositories/news_repository.dart
Normal file
6
lib/domain/repositories/news_repository.dart
Normal file
@@ -0,0 +1,6 @@
|
||||
import '../entities/news.dart';
|
||||
|
||||
abstract class NewsRepository {
|
||||
Future<List<NewsEntity>> getNews();
|
||||
Future<NewsEntity> getNewsById(int id);
|
||||
}
|
||||
12
lib/domain/repositories/notification_repository.dart
Normal file
12
lib/domain/repositories/notification_repository.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import 'package:be_happy/domain/entities/client_notification.dart';
|
||||
|
||||
abstract class NotificationRepository {
|
||||
/// Устанавливает постоянное SSE-соединение и возвращает поток уведомлений
|
||||
Stream<ClientNotification> getNotificationsStream();
|
||||
|
||||
/// Отменяет уведомление по ID
|
||||
Future<ClientNotification> cancelNotification(int id);
|
||||
|
||||
/// Закрывает SSE-соединение
|
||||
void closeStream();
|
||||
}
|
||||
20
lib/domain/repositories/payment_repository.dart
Normal file
20
lib/domain/repositories/payment_repository.dart
Normal file
@@ -0,0 +1,20 @@
|
||||
import '../../core/result.dart';
|
||||
import '../entities/payment_card.dart';
|
||||
|
||||
abstract class PaymentRepository {
|
||||
Future<Result<List<PaymentCard>>> getPaymentCards();
|
||||
|
||||
Future<Result<void>> addPaymentCard({
|
||||
required String cardNumber,
|
||||
required String cardHolder,
|
||||
required String expiryMonth,
|
||||
required String expiryYear,
|
||||
required String cvv,
|
||||
});
|
||||
|
||||
Future<Result<void>> setMainPaymentCard(int cardId);
|
||||
|
||||
Future<Result<void>> removePaymentCard(int cardId);
|
||||
|
||||
Future<Result<bool>> activateSubscription(int optionId);
|
||||
}
|
||||
9
lib/domain/repositories/pin_repository.dart
Normal file
9
lib/domain/repositories/pin_repository.dart
Normal file
@@ -0,0 +1,9 @@
|
||||
import '../entities/user_auth_data.dart';
|
||||
|
||||
abstract class PinRepository {
|
||||
Future<String?> getSavedPin();
|
||||
|
||||
Future<void> savePin(String? pin);
|
||||
|
||||
Future<void> removePin();
|
||||
}
|
||||
12
lib/domain/repositories/profile_repository.dart
Normal file
12
lib/domain/repositories/profile_repository.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import 'dart:io';
|
||||
|
||||
import '../entities/user_check_flags.dart';
|
||||
import '../entities/user_profile.dart';
|
||||
|
||||
abstract class UserProfileRepository {
|
||||
Future<UserProfile> getProfile();
|
||||
Future<UserProfile?> updateProfile(UserProfile profile);
|
||||
Future<int?> uploadProfilePhoto(File imageFile);
|
||||
Future<UserCheckFlags?> checkUser();
|
||||
}
|
||||
|
||||
55
lib/domain/repositories/scooter_repository.dart
Normal file
55
lib/domain/repositories/scooter_repository.dart
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:be_happy/domain/entities/active_scooter_order.dart';
|
||||
|
||||
import '../../core/result.dart';
|
||||
import '../entities/point.dart';
|
||||
import '../entities/scooter.dart';
|
||||
import '../entities/subscription.dart';
|
||||
import '../entities/tariff.dart';
|
||||
import '../entities/scooter_order.dart';
|
||||
|
||||
abstract class ScooterRepository {
|
||||
Future<List<Scooter>> getScooters(List<double> area, int page, int pageSize);
|
||||
Future<Result<Scooter?>> getScooter(int id);
|
||||
Future<Result<List<Tariff>>> getAvailableTariffs(int scooterId);
|
||||
Future<Result<List<Subscription>>> getAvailableSubscriptions();
|
||||
Future<Result<Subscription>> getSubscriptionById(int id);
|
||||
Future<Result<List<Subscription>>> getClientSubscriptions();
|
||||
Future<Result<ScooterOrder>> bookScooter({
|
||||
required int scooterId,
|
||||
required int planId,
|
||||
int? subscriptionId,
|
||||
int? cardId,
|
||||
required bool isBalance,
|
||||
required bool isInsurance,
|
||||
});
|
||||
Future<Result<ScooterOrder>> startRide(int orderId);
|
||||
Future<Result<ScooterOrder>> cancelRide(int orderId);
|
||||
Future<Result<ScooterOrder>> pauseRide(int orderId);
|
||||
Future<Result<ScooterOrder>> resumeRide(int orderId);
|
||||
Future<Result<ScooterOrder>> finishRide(int orderId, List<int> files);
|
||||
Future<Result<ScooterOrder>> payRide(int orderId);
|
||||
Future<Result<List<ScooterOrder>>> getClientOrders();
|
||||
Future<Result<List<int>>> uploadScooterPhotos(List<File> images);
|
||||
Future<Result<ActiveScooterOrder>> updateScooterOrderData({
|
||||
required int orderId,
|
||||
});
|
||||
Future<Result<ScooterOrder>> payScooterOrderWithPhotos({
|
||||
required int orderId,
|
||||
required int? cardId,
|
||||
required bool isBalance,
|
||||
});
|
||||
Future<Result<ScooterOrder>> getScooterOrderById(int id);
|
||||
|
||||
Future<Result<List<ScooterOrder>>> getScooterOrderHistory({
|
||||
int page = 1,
|
||||
int pageSize = 20,
|
||||
});
|
||||
|
||||
Future<Result<Scooter?>> getScooterByTitle(String title);
|
||||
|
||||
Future<Result<List<Point>>> getScooterOrderRouteHistory(int id);
|
||||
|
||||
}
|
||||
6
lib/domain/repositories/zone_repository.dart
Normal file
6
lib/domain/repositories/zone_repository.dart
Normal file
@@ -0,0 +1,6 @@
|
||||
import '../entities/zone.dart';
|
||||
|
||||
abstract class ZoneRepository {
|
||||
Future<List<Zone>> getZones(List<double> area, int page, int pageSize);
|
||||
}
|
||||
|
||||
4
lib/domain/service/device_info_service.dart
Normal file
4
lib/domain/service/device_info_service.dart
Normal file
@@ -0,0 +1,4 @@
|
||||
abstract class DeviceInfoService {
|
||||
Future<String?> getSystemId(); //SSAID - Android, IDFV - iOS (Vendor ID - один идентификатор для всех приложений одного разработчика, уникальный для одного устройства)
|
||||
Future<String> getDeviceModel();
|
||||
}
|
||||
16
lib/domain/service/security_service.dart
Normal file
16
lib/domain/service/security_service.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import 'package:be_happy/domain/entities/user_auth_data.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
|
||||
abstract class SecurityService {
|
||||
Future<void> saveTokens(UserAuthData data);
|
||||
Future<void> removeTokens();
|
||||
Future<String?> getRefreshToken();
|
||||
Future<String?> getAccessToken();
|
||||
|
||||
// Методы для работы с полными номерами карт
|
||||
Future<void> saveCardFullNumber(int cardId, String fullCardNumber);
|
||||
Future<String?> getCardFullNumber(int cardId);
|
||||
Future<void> removeCardFullNumber(int cardId);
|
||||
Future<void> clearAllCardsNumbers();
|
||||
// Future<UserAuthData?> getTokens();
|
||||
}
|
||||
12
lib/domain/usecase/activate_subscription_usecase.dart
Normal file
12
lib/domain/usecase/activate_subscription_usecase.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/repositories/payment_repository.dart';
|
||||
|
||||
class ActivateSubscriptionUsecase {
|
||||
final PaymentRepository repository;
|
||||
|
||||
ActivateSubscriptionUsecase(this.repository);
|
||||
|
||||
Future<Result<bool>> call(int optionId) {
|
||||
return repository.activateSubscription(optionId);
|
||||
}
|
||||
}
|
||||
24
lib/domain/usecase/add_payment_card_usecase.dart
Normal file
24
lib/domain/usecase/add_payment_card_usecase.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
import '../repositories/payment_repository.dart';
|
||||
import '../../core/result.dart';
|
||||
|
||||
class AddPaymentCardUsecase {
|
||||
final PaymentRepository repository;
|
||||
|
||||
AddPaymentCardUsecase(this.repository);
|
||||
|
||||
Future<Result<void>> call({
|
||||
required String cardNumber,
|
||||
required String cardHolder,
|
||||
required String expiryMonth,
|
||||
required String expiryYear,
|
||||
required String cvv,
|
||||
}) {
|
||||
return repository.addPaymentCard(
|
||||
cardNumber: cardNumber,
|
||||
cardHolder: cardHolder,
|
||||
expiryMonth: expiryMonth,
|
||||
expiryYear: expiryYear,
|
||||
cvv: cvv,
|
||||
);
|
||||
}
|
||||
}
|
||||
27
lib/domain/usecase/book_scooter_usecase.dart
Normal file
27
lib/domain/usecase/book_scooter_usecase.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/scooter_order.dart';
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
class BookScooterUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
BookScooterUsecase(this.repository);
|
||||
|
||||
Future<Result<ScooterOrder>> call({
|
||||
required int scooterId,
|
||||
required int planId,
|
||||
int? subscriptionId,
|
||||
int? cardId,
|
||||
required bool isBalance,
|
||||
required bool isInsurance,
|
||||
}) {
|
||||
return repository.bookScooter(
|
||||
scooterId: scooterId,
|
||||
planId: planId,
|
||||
subscriptionId: subscriptionId,
|
||||
cardId: cardId,
|
||||
isBalance: isBalance,
|
||||
isInsurance: isInsurance,
|
||||
);
|
||||
}
|
||||
}
|
||||
12
lib/domain/usecase/cancel_notification_usecase.dart
Normal file
12
lib/domain/usecase/cancel_notification_usecase.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import 'package:be_happy/domain/entities/client_notification.dart';
|
||||
import 'package:be_happy/domain/repositories/notification_repository.dart';
|
||||
|
||||
class CancelNotificationUseCase {
|
||||
final NotificationRepository repository;
|
||||
|
||||
CancelNotificationUseCase(this.repository);
|
||||
|
||||
Future<ClientNotification> call(int id) async {
|
||||
return await repository.cancelNotification(id);
|
||||
}
|
||||
}
|
||||
13
lib/domain/usecase/cancel_ride_usecase.dart
Normal file
13
lib/domain/usecase/cancel_ride_usecase.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/scooter_order.dart';
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
class CancelRideUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
CancelRideUsecase(this.repository);
|
||||
|
||||
Future<Result<ScooterOrder>> call(int orderId) {
|
||||
return repository.cancelRide(orderId);
|
||||
}
|
||||
}
|
||||
27
lib/domain/usecase/change_pin_usecase.dart
Normal file
27
lib/domain/usecase/change_pin_usecase.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
import 'package:be_happy/domain/repositories/pin_repository.dart';
|
||||
|
||||
import '../repositories/auth_repository.dart';
|
||||
|
||||
class ChangePinUseCase {
|
||||
final PinRepository repository;
|
||||
|
||||
ChangePinUseCase(this.repository);
|
||||
|
||||
Future<void> call({
|
||||
required String oldPin,
|
||||
required String newPin,
|
||||
}) async {
|
||||
final savedPin = await repository.getSavedPin();
|
||||
|
||||
if (savedPin != oldPin) {
|
||||
throw Exception('Wrong old PIN');
|
||||
}
|
||||
|
||||
if (newPin.length != 6) {
|
||||
throw Exception('Invalid new PIN');
|
||||
}
|
||||
|
||||
await repository.savePin(newPin);
|
||||
}
|
||||
}
|
||||
|
||||
12
lib/domain/usecase/check_user_usecase.dart
Normal file
12
lib/domain/usecase/check_user_usecase.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import '../entities/user_check_flags.dart';
|
||||
import '../repositories/profile_repository.dart';
|
||||
|
||||
class CheckUserUseCase {
|
||||
final UserProfileRepository repository;
|
||||
|
||||
CheckUserUseCase(this.repository);
|
||||
|
||||
Future<UserCheckFlags?> call() {
|
||||
return repository.checkUser();
|
||||
}
|
||||
}
|
||||
27
lib/domain/usecase/create_pin_usecase.dart
Normal file
27
lib/domain/usecase/create_pin_usecase.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
import 'package:be_happy/domain/repositories/pin_repository.dart';
|
||||
|
||||
import '../repositories/auth_repository.dart';
|
||||
|
||||
class CreatePinUseCase {
|
||||
final PinRepository repository;
|
||||
|
||||
CreatePinUseCase(this.repository);
|
||||
|
||||
Future<void> call(String pin) async {
|
||||
_validate(pin);
|
||||
|
||||
final hashed = _hash(pin);
|
||||
await repository.savePin(hashed);
|
||||
}
|
||||
|
||||
void _validate(String pin) {
|
||||
if (pin.length != 6) {
|
||||
throw Exception('PIN must be 6 digits');
|
||||
}
|
||||
}
|
||||
|
||||
String _hash(String pin) {
|
||||
// временно просто pin
|
||||
return pin;
|
||||
}
|
||||
}
|
||||
13
lib/domain/usecase/finish_ride_usecase.dart
Normal file
13
lib/domain/usecase/finish_ride_usecase.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/scooter_order.dart';
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
class FinishRideUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
FinishRideUsecase(this.repository);
|
||||
|
||||
Future<Result<ScooterOrder>> call(int orderId, List<int> files) {
|
||||
return repository.finishRide(orderId, files);
|
||||
}
|
||||
}
|
||||
11
lib/domain/usecase/get_address_by_point_usecase.dart
Normal file
11
lib/domain/usecase/get_address_by_point_usecase.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
import 'package:be_happy/data/network/geocoding_remote_datasource.dart';
|
||||
|
||||
class GetAddressByPointUsecase {
|
||||
final GeocodingRemoteDataSource dataSource;
|
||||
|
||||
GetAddressByPointUsecase(this.dataSource);
|
||||
|
||||
Future<String> call(double latitude, double longitude) {
|
||||
return dataSource.getAddressFromPoint(latitude: latitude, longitude: longitude);
|
||||
}
|
||||
}
|
||||
15
lib/domain/usecase/get_available_scooters_usecase.dart
Normal file
15
lib/domain/usecase/get_available_scooters_usecase.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:be_happy/domain/entities/scooter.dart';
|
||||
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
|
||||
class GetAvailableScootersUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
GetAvailableScootersUsecase(this.repository);
|
||||
|
||||
Future<List<Scooter>> call(List<double> area, int page, int pageSize) {
|
||||
return repository.getScooters(area, page, pageSize);
|
||||
}
|
||||
}
|
||||
|
||||
14
lib/domain/usecase/get_available_subscriptions_usecase.dart
Normal file
14
lib/domain/usecase/get_available_subscriptions_usecase.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/subscription.dart';
|
||||
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
class GetAvailableSubscriptionsUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
GetAvailableSubscriptionsUsecase(this.repository);
|
||||
|
||||
Future<Result<List<Subscription>>> call() {
|
||||
return repository.getAvailableSubscriptions();
|
||||
}
|
||||
}
|
||||
14
lib/domain/usecase/get_available_tariffs_usecase.dart
Normal file
14
lib/domain/usecase/get_available_tariffs_usecase.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/tariff.dart';
|
||||
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
class GetAvailableTariffsUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
GetAvailableTariffsUsecase(this.repository);
|
||||
|
||||
Future<Result<List<Tariff>>> call(int scooterId) {
|
||||
return repository.getAvailableTariffs(scooterId);
|
||||
}
|
||||
}
|
||||
15
lib/domain/usecase/get_available_zones_usecase.dart
Normal file
15
lib/domain/usecase/get_available_zones_usecase.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
import '../entities/zone.dart';
|
||||
import '../repositories/zone_repository.dart';
|
||||
|
||||
|
||||
class GetAvailableZonesUsecase {
|
||||
final ZoneRepository repository;
|
||||
|
||||
GetAvailableZonesUsecase(this.repository);
|
||||
|
||||
Future<List<Zone>?> call(List<double> area, int page, int pageSize) {
|
||||
return repository.getZones(area, page, pageSize);
|
||||
}
|
||||
}
|
||||
|
||||
13
lib/domain/usecase/get_certificates_usecase.dart
Normal file
13
lib/domain/usecase/get_certificates_usecase.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import '../entities/certificate.dart';
|
||||
import '../repositories/certificate_repository.dart';
|
||||
import '../../core/result.dart';
|
||||
|
||||
class GetCertificatesUsecase {
|
||||
final CertificateRepository repository;
|
||||
|
||||
GetCertificatesUsecase(this.repository);
|
||||
|
||||
Future<Result<List<Certificate>>> call() async {
|
||||
return await repository.getCertificates();
|
||||
}
|
||||
}
|
||||
15
lib/domain/usecase/get_client_orders_usecase.dart
Normal file
15
lib/domain/usecase/get_client_orders_usecase.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/scooter_order.dart';
|
||||
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
|
||||
class GetClientOrdersUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
GetClientOrdersUsecase(this.repository);
|
||||
|
||||
Future<Result<List<ScooterOrder>>> call() {
|
||||
return repository.getClientOrders();
|
||||
}
|
||||
}
|
||||
20
lib/domain/usecase/get_client_subscriptions_usecase.dart
Normal file
20
lib/domain/usecase/get_client_subscriptions_usecase.dart
Normal file
@@ -0,0 +1,20 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/scooter_order.dart';
|
||||
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/subscription.dart';
|
||||
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
class GetClientSubscriptionsUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
GetClientSubscriptionsUsecase(this.repository);
|
||||
|
||||
Future<Result<List<Subscription>>> call() {
|
||||
return repository.getClientSubscriptions();
|
||||
}
|
||||
}
|
||||
12
lib/domain/usecase/get_map_settings_usecase.dart
Normal file
12
lib/domain/usecase/get_map_settings_usecase.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import 'package:be_happy/domain/entities/map_settings.dart';
|
||||
import 'package:be_happy/domain/repositories/app_settings_repository.dart';
|
||||
|
||||
class GetMapSettingsUsecase {
|
||||
AppSettingsRepository repository;
|
||||
|
||||
GetMapSettingsUsecase(this.repository);
|
||||
|
||||
Future<MapSettings> call() {
|
||||
return repository.getMapSettings();
|
||||
}
|
||||
}
|
||||
12
lib/domain/usecase/get_news_by_id_usecase.dart
Normal file
12
lib/domain/usecase/get_news_by_id_usecase.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import '../entities/news.dart';
|
||||
import '../repositories/news_repository.dart';
|
||||
|
||||
class GetNewsByIdUsecase {
|
||||
final NewsRepository repository;
|
||||
|
||||
GetNewsByIdUsecase(this.repository);
|
||||
|
||||
Future<NewsEntity> call(int id) {
|
||||
return repository.getNewsById(id);
|
||||
}
|
||||
}
|
||||
12
lib/domain/usecase/get_notifications_stream_usecase.dart
Normal file
12
lib/domain/usecase/get_notifications_stream_usecase.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import 'package:be_happy/domain/entities/client_notification.dart';
|
||||
import 'package:be_happy/domain/repositories/notification_repository.dart';
|
||||
|
||||
class GetNotificationsStreamUseCase {
|
||||
final NotificationRepository repository;
|
||||
|
||||
GetNotificationsStreamUseCase(this.repository);
|
||||
|
||||
Stream<ClientNotification> call() {
|
||||
return repository.getNotificationsStream();
|
||||
}
|
||||
}
|
||||
31
lib/domain/usecase/get_payment_cards_usecase.dart
Normal file
31
lib/domain/usecase/get_payment_cards_usecase.dart
Normal file
@@ -0,0 +1,31 @@
|
||||
import 'package:be_happy/domain/service/security_service.dart';
|
||||
|
||||
import '../entities/payment_card.dart';
|
||||
import '../repositories/payment_repository.dart';
|
||||
import '../../core/result.dart';
|
||||
|
||||
class GetPaymentCardsUsecase {
|
||||
final PaymentRepository repository;
|
||||
final SecurityService securityService;
|
||||
|
||||
GetPaymentCardsUsecase(this.repository, this.securityService);
|
||||
|
||||
Future<Result<List<PaymentCard>>> call() async {
|
||||
final result = await repository.getPaymentCards();
|
||||
|
||||
if (result is Failure) {
|
||||
return result;
|
||||
}
|
||||
|
||||
final cards = (result as Success).data as List<PaymentCard>;
|
||||
|
||||
// Для каждой карты получаем полный номер из локального хранилища
|
||||
/*final cardsWithFullNumbers = <PaymentCard>[];
|
||||
for (final card in cards) {
|
||||
final fullNumber = await securityService.getCardFullNumber(card.id);
|
||||
cardsWithFullNumbers.add(card.copyWith(fullCardNumber: fullNumber));
|
||||
}*/
|
||||
|
||||
return Success(cards);
|
||||
}
|
||||
}
|
||||
12
lib/domain/usecase/get_pedestrian_routes_usecase.dart
Normal file
12
lib/domain/usecase/get_pedestrian_routes_usecase.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import 'package:be_happy/data/network/geocoding_remote_datasource.dart';
|
||||
import 'package:yandex_mapkit/yandex_mapkit.dart';
|
||||
|
||||
class GetPedestrianRoutesUsecase {
|
||||
final GeocodingRemoteDataSource dataSource;
|
||||
|
||||
GetPedestrianRoutesUsecase(this.dataSource);
|
||||
|
||||
Future<List<MasstransitRoute>?> call(Point userPosition, Point targetPosition) {
|
||||
return dataSource.getPedestrianRoutes(userPosition, targetPosition);
|
||||
}
|
||||
}
|
||||
13
lib/domain/usecase/get_profile_usecase.dart
Normal file
13
lib/domain/usecase/get_profile_usecase.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import '../entities/user_profile.dart';
|
||||
import '../repositories/profile_repository.dart';
|
||||
|
||||
class GetProfileUseCase {
|
||||
final UserProfileRepository repository;
|
||||
|
||||
GetProfileUseCase(this.repository);
|
||||
|
||||
Future<UserProfile> call() {
|
||||
return repository.getProfile();
|
||||
}
|
||||
}
|
||||
|
||||
14
lib/domain/usecase/get_scooter_by_title_usecase.dart
Normal file
14
lib/domain/usecase/get_scooter_by_title_usecase.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/scooter.dart';
|
||||
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
class GetScooterByTitleUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
GetScooterByTitleUsecase(this.repository);
|
||||
|
||||
Future<Result<Scooter?>> call(String title) {
|
||||
return repository.getScooterByTitle(title);
|
||||
}
|
||||
}
|
||||
13
lib/domain/usecase/get_scooter_order_by_id_usecase.dart
Normal file
13
lib/domain/usecase/get_scooter_order_by_id_usecase.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import '../entities/scooter_order.dart';
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
class GetScooterOrderByIdUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
GetScooterOrderByIdUsecase(this.repository);
|
||||
|
||||
Future<Result<ScooterOrder>> call(int id) {
|
||||
return repository.getScooterOrderById(id);
|
||||
}
|
||||
}
|
||||
19
lib/domain/usecase/get_scooter_order_history_usecase.dart
Normal file
19
lib/domain/usecase/get_scooter_order_history_usecase.dart
Normal file
@@ -0,0 +1,19 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/scooter_order.dart';
|
||||
import 'package:be_happy/domain/repositories/scooter_repository.dart';
|
||||
|
||||
class GetScooterOrderHistoryUsecase {
|
||||
final ScooterRepository _repository;
|
||||
|
||||
GetScooterOrderHistoryUsecase(this._repository);
|
||||
|
||||
Future<Result<List<ScooterOrder>>> call({
|
||||
int page = 1,
|
||||
int pageSize = 20,
|
||||
}) async {
|
||||
return await _repository.getScooterOrderHistory(
|
||||
page: page,
|
||||
pageSize: pageSize,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/point.dart';
|
||||
import 'package:be_happy/domain/repositories/scooter_repository.dart';
|
||||
|
||||
class GetScooterOrderRouteHistoryUsecase {
|
||||
final ScooterRepository _repository;
|
||||
|
||||
GetScooterOrderRouteHistoryUsecase(this._repository);
|
||||
|
||||
Future<Result<List<Point>>> call(int id) async {
|
||||
return await _repository.getScooterOrderRouteHistory(id);
|
||||
}
|
||||
}
|
||||
16
lib/domain/usecase/get_scooter_usecase.dart
Normal file
16
lib/domain/usecase/get_scooter_usecase.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/scooter.dart';
|
||||
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
|
||||
class GetScooterUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
GetScooterUsecase(this.repository);
|
||||
|
||||
Future<Result<Scooter?>> call(int id) {
|
||||
return repository.getScooter(id);
|
||||
}
|
||||
}
|
||||
|
||||
14
lib/domain/usecase/get_subscription_by_id_usecase.dart
Normal file
14
lib/domain/usecase/get_subscription_by_id_usecase.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import 'package:be_happy/domain/entities/subscription.dart';
|
||||
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
class GetSubscriptionByIdUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
GetSubscriptionByIdUsecase(this.repository);
|
||||
|
||||
Future<Result<Subscription>> call(int id) {
|
||||
return repository.getSubscriptionById(id);
|
||||
}
|
||||
}
|
||||
17
lib/domain/usecase/is_pin_set_usecase.dart
Normal file
17
lib/domain/usecase/is_pin_set_usecase.dart
Normal file
@@ -0,0 +1,17 @@
|
||||
import 'package:be_happy/domain/repositories/pin_repository.dart';
|
||||
|
||||
import '../repositories/auth_repository.dart';
|
||||
|
||||
class IsPinSetUsecase {
|
||||
final PinRepository repository;
|
||||
|
||||
IsPinSetUsecase(this.repository);
|
||||
|
||||
Future<bool> call() async {
|
||||
if (await repository.getSavedPin() == null) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
lib/domain/usecase/login_usecase.dart
Normal file
11
lib/domain/usecase/login_usecase.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
import '../repositories/auth_repository.dart';
|
||||
|
||||
class LoginUseCase {
|
||||
final AuthRepository _repository;
|
||||
|
||||
LoginUseCase(this._repository);
|
||||
|
||||
Future<String> execute(String phone) async {
|
||||
return await _repository.login(phone);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user