# Conflicts:
#	lib/presentation/navigation/app_router.dart
#	pubspec.yaml
This commit is contained in:
2026-08-11 00:14:00 +03:00
parent c9b8d143d1
commit 182be1049b
351 changed files with 24566 additions and 22898 deletions

View File

@@ -1,93 +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);
}
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);
}

View File

@@ -1,29 +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);
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);
}

View File

@@ -1,13 +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);
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);
}

View File

@@ -1,8 +1,8 @@
class AuthBlockException implements Exception {
String description = "Неверный код. Вы временно заблокированы, попробуйте позже.";
AuthBlockException();
@override
String toString() => description;
}
class AuthBlockException implements Exception {
String description = "Неверный код. Вы временно заблокированы, попробуйте позже.";
AuthBlockException();
@override
String toString() => description;
}

View File

@@ -1,9 +1,9 @@
class AuthException implements Exception {
int attemptsLeft;
String? description;
AuthException(this.description, this.attemptsLeft);
@override
String toString() => description ?? "Ошибка авторизации";
}
class AuthException implements Exception {
int attemptsLeft;
String? description;
AuthException(this.description, this.attemptsLeft);
@override
String toString() => description ?? "Ошибка авторизации";
}

View File

@@ -1,8 +1,8 @@
class RouteHistoryNotFoundException implements Exception {
final String message;
RouteHistoryNotFoundException({this.message = "История маршрута не найдена"});
@override
String toString() => message;
}
class RouteHistoryNotFoundException implements Exception {
final String message;
RouteHistoryNotFoundException({this.message = "История маршрута не найдена"});
@override
String toString() => message;
}

View File

@@ -1,8 +1,8 @@
class ScooterNotFoundException implements Exception {
final String message;
ScooterNotFoundException({this.message = "Самокат не найден"});
@override
String toString() => message;
}
class ScooterNotFoundException implements Exception {
final String message;
ScooterNotFoundException({this.message = "Самокат не найден"});
@override
String toString() => message;
}

View File

@@ -1,5 +1,5 @@
class UnauthorizedException implements Exception {
@override
String toString() => "Ошибка авторизации. Пользователь не авторизован";
}
class UnauthorizedException implements Exception {
@override
String toString() => "Ошибка авторизации. Пользователь не авторизован";
}

View File

@@ -1,6 +1,6 @@
class WrongZoneException implements Exception {
final String message;
WrongZoneException({required this.message});
}
class WrongZoneException implements Exception {
final String message;
WrongZoneException({required this.message});
}

View File

@@ -1,26 +1,26 @@
import 'package:dio/dio.dart';
import 'package:be_happy/presentation/viewmodel/splash_bloc.dart';
import 'package:be_happy/presentation/event/spalsh_event.dart';
import '../../di/service_locator.dart';
class AuthInterceptor extends Interceptor {
AuthInterceptor();
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
final String path = err.requestOptions.path;
if (err.response?.statusCode == 401) {
if (!path.contains('/auth/client/refresh') && !path.contains('/auth/client/login')) {
print('Interceptor: 401 на обычном запросе. Пытаемся обновить токен...');
getIt<SplashBloc>().add(AuthCheckRequested());
} else {
print('Interceptor: 401 на запросе авторизации. Пробрасываем ошибку дальше.');
}
}
return super.onError(err, handler);
}
import 'package:dio/dio.dart';
import 'package:be_happy/presentation/viewmodel/splash_bloc.dart';
import 'package:be_happy/presentation/event/spalsh_event.dart';
import '../../di/service_locator.dart';
class AuthInterceptor extends Interceptor {
AuthInterceptor();
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
final String path = err.requestOptions.path;
if (err.response?.statusCode == 401) {
if (!path.contains('/auth/client/refresh') && !path.contains('/auth/client/login')) {
print('Interceptor: 401 на обычном запросе. Пытаемся обновить токен...');
getIt<SplashBloc>().add(AuthCheckRequested());
} else {
print('Interceptor: 401 на запросе авторизации. Пробрасываем ошибку дальше.');
}
}
return super.onError(err, handler);
}
}

View File

@@ -1,13 +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"] ?? "",
);
}
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"] ?? "",
);
}
}

View File

@@ -1,89 +1,89 @@
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: _parseUtcDate(createdAt),
canceledAt: canceledAt != null ? _parseUtcDate(canceledAt!) : null,
readAt: readAt != null ? _parseUtcDate(readAt!) : null,
);
}
DateTime _parseUtcDate(String dateString) {
if (dateString.endsWith('Z') || dateString.contains('+') || dateString.contains('-')) {
return DateTime.parse(dateString).toLocal();
}
return DateTime.parse('${dateString}Z').toLocal();
}
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;
}
}
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: _parseUtcDate(createdAt),
canceledAt: canceledAt != null ? _parseUtcDate(canceledAt!) : null,
readAt: readAt != null ? _parseUtcDate(readAt!) : null,
);
}
DateTime _parseUtcDate(String dateString) {
if (dateString.endsWith('Z') || dateString.contains('+') || dateString.contains('-')) {
return DateTime.parse(dateString).toLocal();
}
return DateTime.parse('${dateString}Z').toLocal();
}
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;
}
}
}

View File

@@ -1,9 +1,9 @@
class LoginRequestDto {
final String phone;
LoginRequestDto({required this.phone});
Map<String, dynamic> toJson() {
return {"phone": phone};
}
class LoginRequestDto {
final String phone;
LoginRequestDto({required this.phone});
Map<String, dynamic> toJson() {
return {"phone": phone};
}
}

View File

@@ -1,25 +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,
};
}
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,
};
}
}

View File

@@ -1,45 +1,45 @@
import '../../domain/entities/payment_card.dart';
class PaymentCardResponseDto {
final int id;
final String bindingId;
final int expirationMonth;
final int expirationYear;
final String cardHolder;
final String cardLastNumber;
final String type;
final bool isMain;
PaymentCardResponseDto({
required this.id,
required this.bindingId,
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,
bindingId: json['bindingId'] as String,
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,
bindingId: bindingId,
cardLastNumber: cardLastNumber,
isMain: isMain,
);
}
}
import '../../domain/entities/payment_card.dart';
class PaymentCardResponseDto {
final int id;
final String bindingId;
final int expirationMonth;
final int expirationYear;
final String cardHolder;
final String cardLastNumber;
final String type;
final bool isMain;
PaymentCardResponseDto({
required this.id,
required this.bindingId,
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,
bindingId: json['bindingId'] as String,
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,
bindingId: bindingId,
cardLastNumber: cardLastNumber,
isMain: isMain,
);
}
}

View File

@@ -1,25 +1,25 @@
import '../../domain/entities/promo_code_result.dart';
class PromoCodeResponseDto {
final bool success;
final double balance;
PromoCodeResponseDto({
required this.success,
required this.balance,
});
factory PromoCodeResponseDto.fromJson(Map<String, dynamic> json) {
return PromoCodeResponseDto(
success: json['success'] as bool,
balance: (json['balance'] as num).toDouble(),
);
}
PromoCodeResult toEntity() {
return PromoCodeResult(
success: success,
balance: balance,
);
}
import '../../domain/entities/promo_code_result.dart';
class PromoCodeResponseDto {
final bool success;
final double balance;
PromoCodeResponseDto({
required this.success,
required this.balance,
});
factory PromoCodeResponseDto.fromJson(Map<String, dynamic> json) {
return PromoCodeResponseDto(
success: json['success'] as bool,
balance: (json['balance'] as num).toDouble(),
);
}
PromoCodeResult toEntity() {
return PromoCodeResult(
success: success,
balance: balance,
);
}
}

View File

@@ -1,21 +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']),
);
}
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']),
);
}
}

View File

@@ -1,21 +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']),
);
}
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']),
);
}
}

View File

@@ -1,15 +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(),
);
}
}
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(),
);
}
}

View File

@@ -1,15 +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(),
);
}
}
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(),
);
}
}

View File

@@ -1,22 +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,
);
}
}
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,
);
}
}

View File

@@ -1,10 +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};
}
class VerifyCodeRequestDto {
final String code;
final String token;
VerifyCodeRequestDto({required this.code, required this.token});
Map<String, dynamic> toJson() {
return {"code": code, "token": token};
}
}

View File

@@ -1,22 +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']),
);
}
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']),
);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,101 +1,101 @@
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 {
try {
print("From: ${userPosition.latitude}, ${userPosition.longitude}");
print("To: ${targetPosition.latitude}, ${targetPosition.longitude}");
final (session, resultFuture) = await YandexPedestrian.requestRoutes(
points: [
RequestPoint(point: userPosition, requestPointType: RequestPointType.wayPoint),
RequestPoint(point: targetPosition, requestPointType: RequestPointType.wayPoint)
],
fitnessOptions: const FitnessOptions(avoidSteep: false, avoidStairs: false),
timeOptions: const TimeOptions()
);
final result = await resultFuture;
if (result.routes == null || result.routes!.isEmpty) {
print("Маршруты не найдены: список пуст или null");
return [];
}
final route = result.routes!.first;
final distance = route.metadata.weight.walkingDistance?.value;
if (distance != null) {
print("Дистанция до самоката: $distance м");
} else {
print("Дистанция не найдена в метаданных маршрута");
}
return result.routes;
} catch (e, stack) {
print('Pedestrian route error: $e');
print('Stack trace: $stack');
return null;
}
}
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 {
try {
print("From: ${userPosition.latitude}, ${userPosition.longitude}");
print("To: ${targetPosition.latitude}, ${targetPosition.longitude}");
final (session, resultFuture) = await YandexPedestrian.requestRoutes(
points: [
RequestPoint(point: userPosition, requestPointType: RequestPointType.wayPoint),
RequestPoint(point: targetPosition, requestPointType: RequestPointType.wayPoint)
],
fitnessOptions: const FitnessOptions(avoidSteep: false, avoidStairs: false),
timeOptions: const TimeOptions()
);
final result = await resultFuture;
if (result.routes == null || result.routes!.isEmpty) {
print("Маршруты не найдены: список пуст или null");
return [];
}
final route = result.routes!.first;
final distance = route.metadata.weight.walkingDistance?.value;
if (distance != null) {
print("Дистанция до самоката: $distance м");
} else {
print("Дистанция не найдена в метаданных маршрута");
}
return result.routes;
} catch (e, stack) {
print('Pedestrian route error: $e');
print('Stack trace: $stack');
return null;
}
}
}

View File

@@ -1,42 +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);
}
}
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);
}
}

View File

@@ -1,85 +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();
}
}
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();
}
}

View File

@@ -1,59 +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("Неизвестная ошибка"));
}
}
}
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("Неизвестная ошибка"));
}
}
}

View File

@@ -1,46 +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');
}
}
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');
}
}
}

View File

@@ -1,64 +1,64 @@
import 'package:be_happy/domain/entities/client_notification.dart';
import '../../data/network/api_service.dart';
import '../../domain/entities/pagination_meta.dart';
import '../../domain/repositories/notification_repository.dart';
import '../../domain/usecase/get_notifications_usecase.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
}
@override
Future<NotificationsResult> getNotifications({
int page = 1,
int pageSize = 10,
}) async {
try {
final response = await _apiService.getNotifications(
page: page,
pageSize: pageSize,
);
final notifications = (response['data'] as List)
.map((json) => ClientNotificationDto.fromJson(json).toEntity())
.toList();
final pagination = PaginationMeta.fromJson(response['pagination']);
return NotificationsResult(
notifications: notifications,
pagination: pagination,
);
} catch (e, stackTrace) {
throw Exception('Не удалось загрузить уведомления: $e');
}
}
}
import 'package:be_happy/domain/entities/client_notification.dart';
import '../../data/network/api_service.dart';
import '../../domain/entities/pagination_meta.dart';
import '../../domain/repositories/notification_repository.dart';
import '../../domain/usecase/get_notifications_usecase.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
}
@override
Future<NotificationsResult> getNotifications({
int page = 1,
int pageSize = 10,
}) async {
try {
final response = await _apiService.getNotifications(
page: page,
pageSize: pageSize,
);
final notifications = (response['data'] as List)
.map((json) => ClientNotificationDto.fromJson(json).toEntity())
.toList();
final pagination = PaginationMeta.fromJson(response['pagination']);
return NotificationsResult(
notifications: notifications,
pagination: pagination,
);
} catch (e, stackTrace) {
throw Exception('Не удалось загрузить уведомления: $e');
}
}
}

View File

@@ -1,115 +1,115 @@
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<Map<String, dynamic>>> addPaymentCard(
/*required String cardNumber,
required String cardHolder,
required String expiryMonth,
required String expiryYear,
required String cvv,*/
) async {
try {
final result = await apiService.addPaymentCard(
/*cardNumber: cardNumber,
cardHolder: cardHolder,
expirationMonth: int.parse(expiryMonth),
expirationYear: int.parse(expiryYear),
cvv: cvv,*/
);
// await securityService.saveCardFullNumber(cardId, cardNumber);
return Success(result);
} 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, int cardId) async {
try {
final success = await apiService.activateSubscription(optionId: optionId, cardId: cardId);
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("Неизвестная ошибка"));
}
}
}
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<Map<String, dynamic>>> addPaymentCard(
/*required String cardNumber,
required String cardHolder,
required String expiryMonth,
required String expiryYear,
required String cvv,*/
) async {
try {
final result = await apiService.addPaymentCard(
/*cardNumber: cardNumber,
cardHolder: cardHolder,
expirationMonth: int.parse(expiryMonth),
expirationYear: int.parse(expiryYear),
cvv: cvv,*/
);
// await securityService.saveCardFullNumber(cardId, cardNumber);
return Success(result);
} 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, int cardId) async {
try {
final success = await apiService.activateSubscription(optionId: optionId, cardId: cardId);
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("Неизвестная ошибка"));
}
}
}

View File

@@ -1,24 +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");
}
}
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");
}
}

View File

@@ -1,48 +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();
}
}
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();
}
}

View File

@@ -1,23 +1,23 @@
import '../../domain/entities/promo_code_result.dart';
import '../../domain/repositories/promo_code_repository.dart';
import '../models/promo_code_response_dto.dart';
import '../network/api_service.dart';
class PromoCodeRepositoryImpl implements PromoCodeRepository {
final ApiService apiService;
PromoCodeRepositoryImpl(this.apiService);
@override
Future<PromoCodeResult> applyPromoCode(String code) async {
try {
final data = await apiService.applyPromoCode(code);
final dto = PromoCodeResponseDto.fromJson(data);
return dto.toEntity();
} on PromoCodeNotFoundException {
throw Exception('Промокод не найден');
} catch (e) {
throw Exception('Ошибка активации промокода: $e');
}
}
import '../../domain/entities/promo_code_result.dart';
import '../../domain/repositories/promo_code_repository.dart';
import '../models/promo_code_response_dto.dart';
import '../network/api_service.dart';
class PromoCodeRepositoryImpl implements PromoCodeRepository {
final ApiService apiService;
PromoCodeRepositoryImpl(this.apiService);
@override
Future<PromoCodeResult> applyPromoCode(String code) async {
try {
final data = await apiService.applyPromoCode(code);
final dto = PromoCodeResponseDto.fromJson(data);
return dto.toEntity();
} on PromoCodeNotFoundException {
throw Exception('Промокод не найден');
} catch (e) {
throw Exception('Ошибка активации промокода: $e');
}
}
}

View File

@@ -1,428 +1,477 @@
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/client_subscription.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<ClientSubscription>>> getClientSubscriptions() async {
late final Result<List<ClientSubscription>> 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));
} on WrongZoneException catch (e) {
result = Failure(WrongZoneFailure(e.message));
} 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<void>> cancelRide(int orderId) async {
late final Result<void> result;
try {
await _apiService.cancelRide(orderId);
result = Success(null);
} 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<void>> finishRide(int orderId, List<int> files) async {
late final Result<ScooterOrder> result;
try {
await _apiService.finishRide(orderId: orderId, filesId: files);
result = Success(null);
} 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<void>> payRide(int orderId) async {
late final Result<void> result;
try {
await _apiService.payRide(orderId);
result = Success(null);
} 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<void>> payScooterOrderWithPhotos({
required int orderId,
required int? cardId,
required bool isBalance,
}) async {
late final Result<void> result;
try {
final order = await _apiService.payScooterOrderWithPhotos(
orderId: orderId,
cardId: cardId,
isBalance: isBalance,
);
result = Success(null);
} 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;
}
}
import 'dart:io';
import '../../core/failures.dart';
import '../../core/result.dart';
import '../../domain/entities/active_scooter_order.dart';
import '../../domain/entities/client_subscription.dart';
import '../../domain/entities/fine.dart';
import '../../domain/entities/point.dart';
import '../../domain/entities/scooter.dart';
import '../../domain/entities/tariff.dart';
import '../../domain/entities/subscription.dart';
import '../../domain/entities/scooter_order.dart';
import '../../domain/repositories/scooter_repository.dart';
import '../exceptions/auth_block_exception.dart';
import '../exceptions/auth_exception.dart';
import '../exceptions/route_history_not_found_exception.dart';
import '../exceptions/scooter_not_found_exception.dart';
import '../exceptions/unauthorized_exception.dart';
import '../exceptions/wrong_zone_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<ClientSubscription>>> getClientSubscriptions() async {
late final Result<List<ClientSubscription>> 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));
} on WrongZoneException catch (e) {
result = Failure(WrongZoneFailure(e.message));
} 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<void>> cancelRide(int orderId) async {
late final Result<void> result;
try {
await _apiService.cancelRide(orderId);
result = Success(null);
} 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<void>> finishRide(int orderId, List<int> files) async {
late final Result<ScooterOrder> result;
try {
await _apiService.finishRide(orderId: orderId, filesId: files);
result = Success(null);
} 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<void>> payRide(int orderId) async {
late final Result<void> result;
try {
await _apiService.payRide(orderId);
result = Success(null);
} 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<void>> payScooterOrderWithPhotos({
required int orderId,
required int? cardId,
required bool isBalance,
}) async {
late final Result<void> result;
try {
final order = await _apiService.payScooterOrderWithPhotos(
orderId: orderId,
cardId: cardId,
isBalance: isBalance,
);
result = Success(null);
} 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;
}
@override
Future<Result<Fine>> getFineDetails(int orderId) async {
late final Result<Fine> result;
try {
final fine = await _apiService.getFineDetails(orderId);
if (fine != null) {
result = Success(fine);
} else {
result = Failure(UnknownFailure("Не удалось получить данные о штрафе"));
}
} on AuthException catch (e) {
result = Failure(AuthFailure(e.attemptsLeft));
} on UnauthorizedException catch (e) {
result = Failure(AuthFailure(0, message: e.toString()));
} on AuthBlockException catch (e) {
result = Failure(AuthBlockFailure(e.toString()));
} catch (e) {
result = Failure(UnknownFailure("Неизвестная ошибка"));
}
return result;
}
@override
Future<Result<void>> payFine({
required int orderId,
int? cardId,
required bool isBalance,
}) async {
late final Result<void> result;
try {
await _apiService.payFine(
orderId: orderId,
cardId: cardId,
isBalance: isBalance,
);
result = Success(null);
} on AuthException catch (e) {
result = Failure(AuthFailure(e.attemptsLeft));
} on UnauthorizedException catch (e) {
result = Failure(AuthFailure(0, message: e.toString()));
} on AuthBlockException catch (e) {
result = Failure(AuthBlockFailure(e.toString()));
} catch (e) {
result = Failure(UnknownFailure("Неизвестная ошибка"));
}
return result;
}
}

View File

@@ -1,69 +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();
}
}
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();
}
}

View File

@@ -1,15 +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;
}
}
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;
}
}

View File

@@ -1,43 +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;
}
}
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;
}
}

View File

@@ -1,36 +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');
}
}
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');
}
}
}

View File

@@ -1,80 +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;
// }
}
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;
// }
}

View File

@@ -1,406 +1,416 @@
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/interceptor/auth_interceptor.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/repositories/promo_code_repository_impl.dart';
import '../data/service/news_api_service.dart';
import '../domain/repositories/auth_repository.dart';
import '../domain/repositories/news_repository.dart';
import '../domain/repositories/promo_code_repository.dart';
import '../domain/service/device_info_service.dart';
import '../domain/usecase/activate_subscription_usecase.dart';
import '../domain/usecase/apply_promo_code_usecase.dart';
import '../domain/usecase/get_client_subscriptions_usecase.dart';
import '../domain/usecase/get_news_by_id_usecase.dart';
import '../domain/usecase/get_notifications_usecase.dart';
import '../domain/usecase/get_scooter_by_title_usecase.dart';
import '../domain/usecase/get_scooter_order_history_usecase.dart';
import '../domain/usecase/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/notifications_bloc.dart';
import '../presentation/viewmodel/order_history_bloc.dart';
import '../presentation/viewmodel/promo_code_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(/*requestHeader: false, responseHeader:false, */responseBody: true, requestBody: true));
dio.interceptors.add(AuthInterceptor());
// 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()),
);
getIt.registerSingleton<GetNotificationsUsecase>(
GetNotificationsUsecase(getIt<NotificationRepository>()),
);
getIt.registerFactory<NotificationsBloc>(
() => NotificationsBloc(getIt<GetNotificationsUsecase>()),
);
// Blocs
getIt.registerLazySingleton<SplashBloc>(() => SplashBloc(getIt()));
getIt.registerFactory<PhoneAuthBloc>(() => PhoneAuthBloc(getIt()));
getIt.registerFactory<VerifyCodeBloc>(() => VerifyCodeBloc(getIt(), getIt(), getIt()));
getIt.registerLazySingleton<ProfileBloc>(() => ProfileBloc(getIt(), getIt(), getIt()));
getIt.registerFactory<EditProfileBloc>(
() => EditProfileBloc(getIt(), getIt()),
);
getIt.registerFactory<MapBloc>(
() => MapBloc(
getIt(),
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(), getIt(), 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>()),
);
// Repository
getIt.registerSingleton<PromoCodeRepository>(
PromoCodeRepositoryImpl(getIt<ApiService>()),
);
// UseCase
getIt.registerSingleton<ApplyPromoCodeUsecase>(
ApplyPromoCodeUsecase(getIt<PromoCodeRepository>()),
);
// Bloc (factory, т.к. экран создаёт новый экземпляр)
getIt.registerFactory<PromoCodeBloc>(
() => PromoCodeBloc(getIt<ApplyPromoCodeUsecase>()),
);
}
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/interceptor/auth_interceptor.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/repositories/promo_code_repository_impl.dart';
import '../data/service/news_api_service.dart';
import '../domain/repositories/auth_repository.dart';
import '../domain/repositories/news_repository.dart';
import '../domain/repositories/promo_code_repository.dart';
import '../domain/service/device_info_service.dart';
import '../domain/usecase/activate_subscription_usecase.dart';
import '../domain/usecase/apply_promo_code_usecase.dart';
import '../domain/usecase/get_client_subscriptions_usecase.dart';
import '../domain/usecase/get_news_by_id_usecase.dart';
import '../domain/usecase/get_notifications_usecase.dart';
import '../domain/usecase/get_scooter_by_title_usecase.dart';
import '../domain/usecase/get_scooter_order_history_usecase.dart';
import '../domain/usecase/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/notifications_bloc.dart';
import '../presentation/viewmodel/order_history_bloc.dart';
import '../presentation/viewmodel/promo_code_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(
/*requestHeader: false, responseHeader:false, */
responseBody: true,
requestBody: true,
),
);
dio.interceptors.add(AuthInterceptor());
// 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()),
);
getIt.registerSingleton<GetNotificationsUsecase>(
GetNotificationsUsecase(getIt<NotificationRepository>()),
);
getIt.registerFactory<NotificationsBloc>(
() => NotificationsBloc(getIt<GetNotificationsUsecase>()),
);
// Blocs
getIt.registerLazySingleton<SplashBloc>(() => SplashBloc(getIt()));
getIt.registerFactory<PhoneAuthBloc>(() => PhoneAuthBloc(getIt()));
getIt.registerFactory<VerifyCodeBloc>(
() => VerifyCodeBloc(getIt(), getIt(), getIt()),
);
getIt.registerLazySingleton<ProfileBloc>(
() => ProfileBloc(getIt(), getIt(), getIt()),
);
getIt.registerFactory<EditProfileBloc>(
() => EditProfileBloc(getIt(), getIt()),
);
getIt.registerFactory<MapBloc>(
() => MapBloc(
getIt(),
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(), getIt(), 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>(),
getAddressUsecase: getIt<GetAddressByPointUsecase>(),
getPedestrianRoutesUsecase: getIt<GetPedestrianRoutesUsecase>()
),
);
// Repository
getIt.registerSingleton<PromoCodeRepository>(
PromoCodeRepositoryImpl(getIt<ApiService>()),
);
// UseCase
getIt.registerSingleton<ApplyPromoCodeUsecase>(
ApplyPromoCodeUsecase(getIt<PromoCodeRepository>()),
);
// Bloc (factory, т.к. экран создаёт новый экземпляр)
getIt.registerFactory<PromoCodeBloc>(
() => PromoCodeBloc(getIt<ApplyPromoCodeUsecase>()),
);
}

View File

@@ -1,50 +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,
};
}
}
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,
};
}
}

View File

@@ -1,94 +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?,
);
}
}
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?,
);
}
}

View File

@@ -1,58 +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,
);
}
}
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,
);
}
}

View File

@@ -1,24 +1,24 @@
import 'package:be_happy/domain/entities/subscription.dart';
class ClientSubscription {
final int id;
final int subscriptionId;
final Subscription subscription;
final DateTime? expiredAt;
ClientSubscription({
required this.id,
required this.subscriptionId,
required this.subscription,
this.expiredAt,
});
factory ClientSubscription.fromJson(Map<String, dynamic> json) {
return ClientSubscription(
id: json['id'] ?? 0,
subscriptionId: json['subscriptionId'] ?? 0,
subscription: Subscription.fromJson(json['subscription'] as Map<String, dynamic>),
expiredAt: json['expiredAt'] != null ? DateTime.parse(json['expiredAt']) : null,
);
}
import 'package:be_happy/domain/entities/subscription.dart';
class ClientSubscription {
final int id;
final int subscriptionId;
final Subscription subscription;
final DateTime? expiredAt;
ClientSubscription({
required this.id,
required this.subscriptionId,
required this.subscription,
this.expiredAt,
});
factory ClientSubscription.fromJson(Map<String, dynamic> json) {
return ClientSubscription(
id: json['id'] ?? 0,
subscriptionId: json['subscriptionId'] ?? 0,
subscription: Subscription.fromJson(json['subscription'] as Map<String, dynamic>),
expiredAt: json['expiredAt'] != null ? DateTime.parse(json['expiredAt']) : null,
);
}
}

View File

@@ -0,0 +1,76 @@
import 'package:equatable/equatable.dart';
class Fine extends Equatable {
final int id;
final String scooterNumber;
final String date;
final String description;
final double amount;
final String amountPrint;
final List<String> photoUrls;
final bool isPaid;
const Fine({
required this.id,
required this.scooterNumber,
required this.date,
required this.description,
required this.amount,
required this.amountPrint,
required this.photoUrls,
required this.isPaid,
});
factory Fine.fromJson(Map<String, dynamic> json, {String? scooterNumber}) {
final List<dynamic> filesJson = json['files'] ?? [];
final List<String> photos = filesJson
.map((file) => file['path'] as String? ?? file['filename'] as String? ?? '')
.where((path) => path.isNotEmpty)
.toList();
// Форматирование даты из createdAt (2026-08-07T09:15:26.565Z -> 07-08-2026)
String formattedDate = '';
if (json['createdAt'] != null) {
final parsedDate = DateTime.tryParse(json['createdAt'].toString());
if (parsedDate != null) {
final day = parsedDate.day.toString().padLeft(2, '0');
final month = parsedDate.month.toString().padLeft(2, '0');
final year = parsedDate.year;
formattedDate = '$day-$month-$year';
}
}
return Fine(
id: json['id'] as int? ?? 0,
scooterNumber: scooterNumber ?? '',
date: formattedDate,
description: json['description'] as String? ?? '',
amount: (json['value'] as num?)?.toDouble() ?? 0.0,
amountPrint: json['valuePrint'] as String? ?? '0,00 BYN',
photoUrls: photos,
isPaid: json['isPaid'] as bool? ?? false,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'description': description,
'value': amount,
'valuePrint': amountPrint,
'isPaid': isPaid,
};
}
@override
List<Object?> get props => [
id,
scooterNumber,
date,
description,
amount,
amountPrint,
photoUrls,
isPaid,
];
}

View File

@@ -1,15 +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,
});
}
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,
});
}

View File

@@ -1,62 +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'],
);
}
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'],
);
}
}

View File

@@ -1,19 +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,
);
}
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,
);
}
}

View File

@@ -1,28 +1,28 @@
class PaginationMeta {
final int total;
final int lastPage;
final int currentPage;
final int totalPerPage;
final int? prevPage;
final int? nextPage;
PaginationMeta({
required this.total,
required this.lastPage,
required this.currentPage,
required this.totalPerPage,
this.prevPage,
this.nextPage,
});
factory PaginationMeta.fromJson(Map<String, dynamic> json) {
return PaginationMeta(
total: json['total'] as int,
lastPage: json['lastPage'] as int,
currentPage: json['currentPage'] as int,
totalPerPage: json['totalPerPage'] as int,
prevPage: json['prevPage'] as int?,
nextPage: json['nextPage'] as int?,
);
}
class PaginationMeta {
final int total;
final int lastPage;
final int currentPage;
final int totalPerPage;
final int? prevPage;
final int? nextPage;
PaginationMeta({
required this.total,
required this.lastPage,
required this.currentPage,
required this.totalPerPage,
this.prevPage,
this.nextPage,
});
factory PaginationMeta.fromJson(Map<String, dynamic> json) {
return PaginationMeta(
total: json['total'] as int,
lastPage: json['lastPage'] as int,
currentPage: json['currentPage'] as int,
totalPerPage: json['totalPerPage'] as int,
prevPage: json['prevPage'] as int?,
nextPage: json['nextPage'] as int?,
);
}
}

View File

@@ -1,27 +1,27 @@
class PaymentCard {
final int id;
final String? bindingId;
final String cardLastNumber;
final bool isMain;
PaymentCard({
required this.id,
required this.bindingId,
required this.cardLastNumber,
required this.isMain,
});
PaymentCard copyWith({
int? id,
String? bindingId,
String? cardLastNumber,
bool? isMain,
}) {
return PaymentCard(
id: id ?? this.id,
bindingId: bindingId ?? this.bindingId,
cardLastNumber: cardLastNumber ?? this.cardLastNumber,
isMain: isMain ?? this.isMain,
);
}
class PaymentCard {
final int id;
final String? bindingId;
final String cardLastNumber;
final bool isMain;
PaymentCard({
required this.id,
required this.bindingId,
required this.cardLastNumber,
required this.isMain,
});
PaymentCard copyWith({
int? id,
String? bindingId,
String? cardLastNumber,
bool? isMain,
}) {
return PaymentCard(
id: id ?? this.id,
bindingId: bindingId ?? this.bindingId,
cardLastNumber: cardLastNumber ?? this.cardLastNumber,
isMain: isMain ?? this.isMain,
);
}
}

View File

@@ -1,12 +1,12 @@
class Point {
final double latitude;
final double longitude;
Point(this.latitude, this.longitude);
@override
String toString() {
return 'Point{latitude: $latitude, longitude: $longitude}';
}
}
class Point {
final double latitude;
final double longitude;
Point(this.latitude, this.longitude);
@override
String toString() {
return 'Point{latitude: $latitude, longitude: $longitude}';
}
}

View File

@@ -1,9 +1,9 @@
class PromoCodeResult {
final bool success;
final double balance;
PromoCodeResult({
required this.success,
required this.balance,
});
class PromoCodeResult {
final bool success;
final double balance;
PromoCodeResult({
required this.success,
required this.balance,
});
}

View File

@@ -1,51 +1,51 @@
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, status: $status, latitude: $latitude, longitude: $longitude, batteryLevel: $batteryLevel, isOnline: $isOnline}';
}
}
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, status: $status, latitude: $latitude, longitude: $longitude, batteryLevel: $batteryLevel, isOnline: $isOnline}';
}
}

View File

@@ -1,154 +1,157 @@
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 есть
final String payTotalPricePrint;
final String unpayTotalPricePrint;
final String totalOrderPricePrint;
ScooterOrder({
required this.id,
required this.scooterId,
required 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,
required this.payTotalPricePrint, // оплачено
required this.unpayTotalPricePrint, //неоплачено
required this.totalOrderPricePrint, //общая
});
factory ScooterOrder.fromJson(Map<String, dynamic> json) {
final paymentInfo = json['paymentInfo'] as Map<String, dynamic>?;
return ScooterOrder(
id: json['id'] ?? 0,
scooterId: json['scooterId'] ?? 0,
scooter: Scooter.fromJson(json['scooter']),
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,
payTotalPricePrint: paymentInfo?['payTotalPricePrint'] ?? '',
unpayTotalPricePrint: paymentInfo?['unpayTotalPricePrint'] ?? '',
totalOrderPricePrint: paymentInfo?['totalOrderPricePrint'] ?? '',
);
}
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'],
);
}
}
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;
final String payTotalPricePrint;
final String unpayTotalPricePrint;
final String totalOrderPricePrint;
final bool hasFine;
ScooterOrder({
required this.id,
required this.scooterId,
required 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,
required this.payTotalPricePrint, // оплачено
required this.unpayTotalPricePrint, //неоплачено
required this.totalOrderPricePrint, //общая
required this.hasFine,
});
factory ScooterOrder.fromJson(Map<String, dynamic> json) {
final paymentInfo = json['paymentInfo'] as Map<String, dynamic>?;
return ScooterOrder(
id: json['id'] ?? 0,
scooterId: json['scooterId'] ?? 0,
scooter: Scooter.fromJson(json['scooter']),
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,
payTotalPricePrint: paymentInfo?['payTotalPricePrint'] ?? '',
unpayTotalPricePrint: paymentInfo?['unpayTotalPricePrint'] ?? '',
totalOrderPricePrint: paymentInfo?['totalOrderPricePrint'] ?? '',
hasFine: paymentInfo?['hasFine'] ?? false,
);
}
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'],
);
}
}

View File

@@ -1,65 +1,65 @@
import 'package:be_happy/domain/entities/subscription_period.dart';
class Subscription {
final int id;
final String title;
final String shortDescription;
final String fullDescription;
final String fullDescriptionJson;
final int planId;
final bool isActive;
final bool isCurrent;
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.fullDescriptionJson,
required this.planId,
required this.isActive,
required this.currency,
this.activeFrom,
this.activeTo,
required this.createdAt,
required this.updatedAt,
required this.isCurrent,
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'] ?? '',
fullDescriptionJson: json['fullDescriptionJson'] ?? '',
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(),
isCurrent: json['isCurrent'] ?? false,
options: optionsData.map((e) => SubscriptionPeriod.fromJson(e as Map<String, dynamic>)).toList(),
);
}
@override
String toString() {
return 'Subscription{id: $id, title: $title, isActive: $isActive}';
}
import 'package:be_happy/domain/entities/subscription_period.dart';
class Subscription {
final int id;
final String title;
final String shortDescription;
final String fullDescription;
final String fullDescriptionJson;
final int planId;
final bool isActive;
final bool isCurrent;
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.fullDescriptionJson,
required this.planId,
required this.isActive,
required this.currency,
this.activeFrom,
this.activeTo,
required this.createdAt,
required this.updatedAt,
required this.isCurrent,
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'] ?? '',
fullDescriptionJson: json['fullDescriptionJson'] ?? '',
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(),
isCurrent: json['isCurrent'] ?? false,
options: optionsData.map((e) => SubscriptionPeriod.fromJson(e as Map<String, dynamic>)).toList(),
);
}
@override
String toString() {
return 'Subscription{id: $id, title: $title, isActive: $isActive}';
}
}

View File

@@ -1,33 +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}';
}
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}';
}
}

View File

@@ -1,51 +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}';
}
}
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}';
}
}

View File

@@ -1,17 +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;
}
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;
}

View File

@@ -1,9 +1,9 @@
class UserAuthData {
final String accessToken;
final String refreshToken;
UserAuthData({
required this.accessToken,
required this.refreshToken,
});
class UserAuthData {
final String accessToken;
final String refreshToken;
UserAuthData({
required this.accessToken,
required this.refreshToken,
});
}

View File

@@ -1,23 +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,
);
}
}
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,
);
}
}

View File

@@ -1,38 +1,38 @@
class UserProfile {
String name;
String birthDate;
String phone;
String email;
double? 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,
double? 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,
);
}
}
class UserProfile {
String name;
String birthDate;
String phone;
String email;
double? 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,
double? 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,
);
}
}

View File

@@ -1,123 +1,123 @@
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;
// Трехмерная структура для поддержки MultiPolygon и дыр (holes):
// geometry[индекс_полигона][индекс_кольца][индекс_точки]
// индекс_кольца == 0 — внешняя граница, > 0 — внутренние вырезы (дыры)
final List<List<List<Point>>> geometry;
final String speedLimit;
Zone({
required this.id,
required this.title,
required this.description,
required this.type,
required this.isActive,
required this.shapeType,
required this.geometry,
required this.speedLimit,
});
// Геттер для обратной совместимости (возвращает внешнее кольцо первого полигона)
List<Point> get points {
if (geometry.isNotEmpty && geometry[0].isNotEmpty) {
return geometry[0][0];
}
return [];
}
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<List<List<Point>>> parsedGeometry = [];
try {
final dynamic decoded = jsonDecode(coordsString);
if (decoded is List && decoded.isNotEmpty) {
if (shapeType == 'Polygon') {
// Структура: [[[lon, lat], [lon, lat], ...], [hole1], ...]
List<List<Point>> polygonRings = [];
for (var ring in decoded) {
if (ring is List) {
List<Point> ringPoints = [];
for (var coord in ring) {
if (coord is List && coord.length >= 2) {
// В GeoJSON сначала идет Longitude, затем Latitude
ringPoints.add(Point(
(coord[1] as num).toDouble(),
(coord[0] as num).toDouble(),
));
}
}
if (ringPoints.isNotEmpty) polygonRings.add(ringPoints);
}
}
if (polygonRings.isNotEmpty) parsedGeometry.add(polygonRings);
} else if (shapeType == 'MultiPolygon') {
// Структура: [[[[lon, lat], ...]], [[[lon, lat], ...]]]
for (var poly in decoded) {
if (poly is List) {
List<List<Point>> polygonRings = [];
for (var ring in poly) {
if (ring is List) {
List<Point> ringPoints = [];
for (var coord in ring) {
if (coord is List && coord.length >= 2) {
ringPoints.add(Point(
(coord[1] as num).toDouble(),
(coord[0] as num).toDouble(),
));
}
}
if (ringPoints.isNotEmpty) polygonRings.add(ringPoints);
}
}
if (polygonRings.isNotEmpty) parsedGeometry.add(polygonRings);
}
}
} else {
// Fallback для LineString или плоских списков
List<Point> ringPoints = [];
for (var coord in decoded) {
if (coord is List && coord.length >= 2) {
ringPoints.add(Point(
(coord[1] as num).toDouble(),
(coord[0] as num).toDouble(),
));
}
}
if (ringPoints.isNotEmpty) parsedGeometry.add([ringPoints]);
}
}
} 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,
geometry: parsedGeometry,
);
}
@override
String toString() {
return 'Zone{id: $id, title: $title, type: $type, polygonsCount: ${geometry.length}}';
}
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;
// Трехмерная структура для поддержки MultiPolygon и дыр (holes):
// geometry[индекс_полигона][индекс_кольца][индекс_точки]
// индекс_кольца == 0 — внешняя граница, > 0 — внутренние вырезы (дыры)
final List<List<List<Point>>> geometry;
final String speedLimit;
Zone({
required this.id,
required this.title,
required this.description,
required this.type,
required this.isActive,
required this.shapeType,
required this.geometry,
required this.speedLimit,
});
// Геттер для обратной совместимости (возвращает внешнее кольцо первого полигона)
List<Point> get points {
if (geometry.isNotEmpty && geometry[0].isNotEmpty) {
return geometry[0][0];
}
return [];
}
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<List<List<Point>>> parsedGeometry = [];
try {
final dynamic decoded = jsonDecode(coordsString);
if (decoded is List && decoded.isNotEmpty) {
if (shapeType == 'Polygon') {
// Структура: [[[lon, lat], [lon, lat], ...], [hole1], ...]
List<List<Point>> polygonRings = [];
for (var ring in decoded) {
if (ring is List) {
List<Point> ringPoints = [];
for (var coord in ring) {
if (coord is List && coord.length >= 2) {
// В GeoJSON сначала идет Longitude, затем Latitude
ringPoints.add(Point(
(coord[1] as num).toDouble(),
(coord[0] as num).toDouble(),
));
}
}
if (ringPoints.isNotEmpty) polygonRings.add(ringPoints);
}
}
if (polygonRings.isNotEmpty) parsedGeometry.add(polygonRings);
} else if (shapeType == 'MultiPolygon') {
// Структура: [[[[lon, lat], ...]], [[[lon, lat], ...]]]
for (var poly in decoded) {
if (poly is List) {
List<List<Point>> polygonRings = [];
for (var ring in poly) {
if (ring is List) {
List<Point> ringPoints = [];
for (var coord in ring) {
if (coord is List && coord.length >= 2) {
ringPoints.add(Point(
(coord[1] as num).toDouble(),
(coord[0] as num).toDouble(),
));
}
}
if (ringPoints.isNotEmpty) polygonRings.add(ringPoints);
}
}
if (polygonRings.isNotEmpty) parsedGeometry.add(polygonRings);
}
}
} else {
// Fallback для LineString или плоских списков
List<Point> ringPoints = [];
for (var coord in decoded) {
if (coord is List && coord.length >= 2) {
ringPoints.add(Point(
(coord[1] as num).toDouble(),
(coord[0] as num).toDouble(),
));
}
}
if (ringPoints.isNotEmpty) parsedGeometry.add([ringPoints]);
}
}
} 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,
geometry: parsedGeometry,
);
}
@override
String toString() {
return 'Zone{id: $id, title: $title, type: $type, polygonsCount: ${geometry.length}}';
}
}

View File

@@ -1,7 +1,7 @@
import 'package:be_happy/domain/entities/map_settings.dart';
abstract class AppSettingsRepository {
Future<MapSettings> getMapSettings();
Future<void> saveMapSettings(MapSettings settings);
import 'package:be_happy/domain/entities/map_settings.dart';
abstract class AppSettingsRepository {
Future<MapSettings> getMapSettings();
Future<void> saveMapSettings(MapSettings settings);
}

View File

@@ -1,14 +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();
}
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();
}

View File

@@ -1,11 +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,
});
}
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,
});
}

View File

@@ -1,3 +1,3 @@
abstract class LaunchRepository {
Future<bool> isFirstLaunch();
}
abstract class LaunchRepository {
Future<bool> isFirstLaunch();
}

View File

@@ -1,6 +1,6 @@
import '../entities/news.dart';
abstract class NewsRepository {
Future<List<NewsEntity>> getNews();
Future<NewsEntity> getNewsById(int id);
import '../entities/news.dart';
abstract class NewsRepository {
Future<List<NewsEntity>> getNews();
Future<NewsEntity> getNewsById(int id);
}

View File

@@ -1,19 +1,19 @@
import 'package:be_happy/domain/entities/client_notification.dart';
import '../usecase/get_notifications_usecase.dart';
abstract class NotificationRepository {
/// Устанавливает постоянное SSE-соединение и возвращает поток уведомлений
Stream<ClientNotification> getNotificationsStream();
/// Отменяет уведомление по ID
Future<ClientNotification> cancelNotification(int id);
/// Закрывает SSE-соединение
void closeStream();
/// получить список уведомлений
Future<NotificationsResult> getNotifications({
int page = 1,
int pageSize = 10,
});}
import 'package:be_happy/domain/entities/client_notification.dart';
import '../usecase/get_notifications_usecase.dart';
abstract class NotificationRepository {
/// Устанавливает постоянное SSE-соединение и возвращает поток уведомлений
Stream<ClientNotification> getNotificationsStream();
/// Отменяет уведомление по ID
Future<ClientNotification> cancelNotification(int id);
/// Закрывает SSE-соединение
void closeStream();
/// получить список уведомлений
Future<NotificationsResult> getNotifications({
int page = 1,
int pageSize = 10,
});}

View File

@@ -1,20 +1,20 @@
import '../../core/result.dart';
import '../entities/payment_card.dart';
abstract class PaymentRepository {
Future<Result<List<PaymentCard>>> getPaymentCards();
Future<Result<Map<String, dynamic>>> 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, int cardId);
import '../../core/result.dart';
import '../entities/payment_card.dart';
abstract class PaymentRepository {
Future<Result<List<PaymentCard>>> getPaymentCards();
Future<Result<Map<String, dynamic>>> 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, int cardId);
}

View File

@@ -1,9 +1,9 @@
import '../entities/user_auth_data.dart';
abstract class PinRepository {
Future<String?> getSavedPin();
Future<void> savePin(String? pin);
Future<void> removePin();
import '../entities/user_auth_data.dart';
abstract class PinRepository {
Future<String?> getSavedPin();
Future<void> savePin(String? pin);
Future<void> removePin();
}

View File

@@ -1,12 +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();
}
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();
}

View File

@@ -1,5 +1,5 @@
import '../entities/promo_code_result.dart';
abstract class PromoCodeRepository {
Future<PromoCodeResult> applyPromoCode(String code);
import '../entities/promo_code_result.dart';
abstract class PromoCodeRepository {
Future<PromoCodeResult> applyPromoCode(String code);
}

View File

@@ -1,56 +1,65 @@
import 'dart:io';
import 'package:be_happy/domain/entities/active_scooter_order.dart';
import '../../core/result.dart';
import '../entities/client_subscription.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<ClientSubscription>>> 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<void>> cancelRide(int orderId);
Future<Result<ScooterOrder>> pauseRide(int orderId);
Future<Result<ScooterOrder>> resumeRide(int orderId);
Future<Result<void>> finishRide(int orderId, List<int> files);
Future<Result<void>> 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<void>> 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);
}
import 'dart:io';
import 'package:be_happy/domain/entities/active_scooter_order.dart';
import '../../core/result.dart';
import '../entities/client_subscription.dart';
import '../entities/fine.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<ClientSubscription>>> 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<void>> cancelRide(int orderId);
Future<Result<ScooterOrder>> pauseRide(int orderId);
Future<Result<ScooterOrder>> resumeRide(int orderId);
Future<Result<void>> finishRide(int orderId, List<int> files);
Future<Result<void>> 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<void>> 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);
Future<Result<Fine>> getFineDetails(int orderId);
Future<Result<void>> payFine({
required int orderId,
int? cardId,
required bool isBalance,
});
}

View File

@@ -1,6 +1,6 @@
import '../entities/zone.dart';
abstract class ZoneRepository {
Future<List<Zone>> getZones(List<double> area, int page, int pageSize);
}
import '../entities/zone.dart';
abstract class ZoneRepository {
Future<List<Zone>> getZones(List<double> area, int page, int pageSize);
}

View File

@@ -1,4 +1,4 @@
abstract class DeviceInfoService {
Future<String?> getSystemId(); //SSAID - Android, IDFV - iOS (Vendor ID - один идентификатор для всех приложений одного разработчика, уникальный для одного устройства)
Future<String> getDeviceModel();
abstract class DeviceInfoService {
Future<String?> getSystemId(); //SSAID - Android, IDFV - iOS (Vendor ID - один идентификатор для всех приложений одного разработчика, уникальный для одного устройства)
Future<String> getDeviceModel();
}

View File

@@ -1,16 +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();
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();
}

View File

@@ -1,12 +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, int cardId) {
return repository.activateSubscription(optionId, cardId);
}
}
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, int cardId) {
return repository.activateSubscription(optionId, cardId);
}
}

View File

@@ -1,24 +1,24 @@
import '../repositories/payment_repository.dart';
import '../../core/result.dart';
class AddPaymentCardUsecase {
final PaymentRepository repository;
AddPaymentCardUsecase(this.repository);
Future<Result<Map<String, dynamic>>> 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,*/
);
}
import '../repositories/payment_repository.dart';
import '../../core/result.dart';
class AddPaymentCardUsecase {
final PaymentRepository repository;
AddPaymentCardUsecase(this.repository);
Future<Result<Map<String, dynamic>>> 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,*/
);
}
}

View File

@@ -1,12 +1,12 @@
import '../entities/promo_code_result.dart';
import '../repositories/promo_code_repository.dart';
class ApplyPromoCodeUsecase {
final PromoCodeRepository repository;
ApplyPromoCodeUsecase(this.repository);
Future<PromoCodeResult> call(String code) {
return repository.applyPromoCode(code);
}
import '../entities/promo_code_result.dart';
import '../repositories/promo_code_repository.dart';
class ApplyPromoCodeUsecase {
final PromoCodeRepository repository;
ApplyPromoCodeUsecase(this.repository);
Future<PromoCodeResult> call(String code) {
return repository.applyPromoCode(code);
}
}

View File

@@ -1,27 +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,
);
}
}
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,
);
}
}

View File

@@ -1,12 +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);
}
}
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);
}
}

View File

@@ -1,13 +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<void>> call(int orderId) {
return repository.cancelRide(orderId);
}
}
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<void>> call(int orderId) {
return repository.cancelRide(orderId);
}
}

View File

@@ -1,27 +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);
}
}
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);
}
}

View File

@@ -1,12 +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();
}
}
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();
}
}

View File

@@ -1,27 +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;
}
}
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;
}
}

View File

@@ -1,13 +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<void>> call(int orderId, List<int> files) {
return repository.finishRide(orderId, files);
}
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<void>> call(int orderId, List<int> files) {
return repository.finishRide(orderId, files);
}
}

View File

@@ -1,11 +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);
}
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);
}
}

View File

@@ -1,15 +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);
}
}
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);
}
}

View File

@@ -1,14 +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();
}
}
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();
}
}

View File

@@ -1,14 +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);
}
}
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);
}
}

View File

@@ -1,15 +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);
}
}
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);
}
}

View File

@@ -1,13 +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();
}
}
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();
}
}

View File

@@ -1,15 +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();
}
}
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();
}
}

View File

@@ -1,21 +1,21 @@
import 'package:be_happy/core/result.dart';
import 'package:be_happy/domain/entities/scooter_order.dart';
import '../entities/client_subscription.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<ClientSubscription>>> call() {
return repository.getClientSubscriptions();
}
}
import 'package:be_happy/core/result.dart';
import 'package:be_happy/domain/entities/scooter_order.dart';
import '../entities/client_subscription.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<ClientSubscription>>> call() {
return repository.getClientSubscriptions();
}
}

View File

@@ -0,0 +1,14 @@
import 'package:be_happy/core/result.dart';
import '../entities/fine.dart';
import '../repositories/scooter_repository.dart';
class GetFineDetailsUsecase {
final ScooterRepository repository;
GetFineDetailsUsecase(this.repository);
Future<Result<Fine>> call(int orderId) {
return repository.getFineDetails(orderId);
}
}

View File

@@ -1,12 +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();
}
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();
}
}

View File

@@ -1,12 +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);
}
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);
}
}

View File

@@ -1,12 +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();
}
}
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();
}
}

View File

@@ -1,23 +1,23 @@
import '../entities/client_notification.dart';
import '../entities/pagination_meta.dart';
import '../repositories/notification_repository.dart';
class GetNotificationsUsecase {
final NotificationRepository repository;
GetNotificationsUsecase(this.repository);
Future<NotificationsResult> call({int page = 1, int pageSize = 10}) {
return repository.getNotifications(page: page, pageSize: pageSize);
}
}
class NotificationsResult {
final List<ClientNotification> notifications;
final PaginationMeta pagination;
NotificationsResult({
required this.notifications,
required this.pagination,
});
import '../entities/client_notification.dart';
import '../entities/pagination_meta.dart';
import '../repositories/notification_repository.dart';
class GetNotificationsUsecase {
final NotificationRepository repository;
GetNotificationsUsecase(this.repository);
Future<NotificationsResult> call({int page = 1, int pageSize = 10}) {
return repository.getNotifications(page: page, pageSize: pageSize);
}
}
class NotificationsResult {
final List<ClientNotification> notifications;
final PaginationMeta pagination;
NotificationsResult({
required this.notifications,
required this.pagination,
});
}

Some files were not shown because too many files have changed in this diff Show More