fix
This commit is contained in:
@@ -32,7 +32,7 @@ class ClientNotification {
|
||||
required this.createdAt,
|
||||
this.canceledAt,
|
||||
this.readAt,
|
||||
});
|
||||
}) ;
|
||||
|
||||
ClientNotification copyWith({
|
||||
int? id,
|
||||
|
||||
28
lib/domain/entities/pagination_meta.dart
Normal file
28
lib/domain/entities/pagination_meta.dart
Normal file
@@ -0,0 +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?,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,9 @@ class ScooterOrder {
|
||||
final String? cancelDescription;
|
||||
final double mileage; //эту
|
||||
final double avgSpeed; //эту и снизу еще 4 есть
|
||||
final String payTotalPricePrint;
|
||||
final String unpayTotalPricePrint;
|
||||
final String totalOrderPricePrint;
|
||||
|
||||
ScooterOrder({
|
||||
required this.id,
|
||||
@@ -57,11 +60,16 @@ class ScooterOrder {
|
||||
this.expiresAt,
|
||||
this.cancelAt,
|
||||
this.cancelDescription,
|
||||
required this.mileage, //эту
|
||||
required this.avgSpeed, //эту и снизу еще 2 есть
|
||||
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,
|
||||
@@ -101,8 +109,11 @@ class ScooterOrder {
|
||||
? DateTime.parse(json['cancelAt'])
|
||||
: null,
|
||||
cancelDescription: json['cancelDescription'],
|
||||
mileage: (json['mileage'] as num?)?.toDouble() ?? 0.0, //эту
|
||||
avgSpeed: (json['avgSpeed'] as num?)?.toDouble() ?? 0.0, //эту
|
||||
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'] ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ class UserProfile {
|
||||
String birthDate;
|
||||
String phone;
|
||||
String email;
|
||||
int? balance;
|
||||
double? balance;
|
||||
int? avatarId;
|
||||
String? avatarUrl;
|
||||
|
||||
@@ -21,7 +21,7 @@ class UserProfile {
|
||||
String? name,
|
||||
String? birthDate,
|
||||
String? email,
|
||||
int? balance,
|
||||
double? balance,
|
||||
int? avatarId,
|
||||
String? avatarUrl,
|
||||
}) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:be_happy/domain/entities/point.dart';
|
||||
|
||||
class Zone {
|
||||
@@ -9,7 +8,10 @@ class Zone {
|
||||
final String type;
|
||||
final bool isActive;
|
||||
final String shapeType;
|
||||
final List<Point> points;
|
||||
// Трехмерная структура для поддержки MultiPolygon и дыр (holes):
|
||||
// geometry[индекс_полигона][индекс_кольца][индекс_точки]
|
||||
// индекс_кольца == 0 — внешняя граница, > 0 — внутренние вырезы (дыры)
|
||||
final List<List<List<Point>>> geometry;
|
||||
final String speedLimit;
|
||||
|
||||
Zone({
|
||||
@@ -19,38 +21,84 @@ class Zone {
|
||||
required this.type,
|
||||
required this.isActive,
|
||||
required this.shapeType,
|
||||
required this.points,
|
||||
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<Point> points = [];
|
||||
List<List<List<Point>>> parsedGeometry = [];
|
||||
|
||||
try {
|
||||
final dynamic decoded = jsonDecode(coordsString);
|
||||
|
||||
if (decoded is List && decoded.isNotEmpty) {
|
||||
List<dynamic> targetList = [];
|
||||
|
||||
if (shapeType == 'Polygon') {
|
||||
// У полигона структура [[[lat, lon], ...]] -> уходим на 1 уровень вглубь
|
||||
targetList = decoded[0] as List<dynamic>;
|
||||
} else {
|
||||
// У LineString структура [[lat, lon], ...] -> используем как есть
|
||||
targetList = decoded;
|
||||
}
|
||||
// Структура: [[[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);
|
||||
|
||||
points = targetList.map((item) {
|
||||
final List<dynamic> coords = item as List<dynamic>;
|
||||
return Point(
|
||||
(coords[1] as num).toDouble(),
|
||||
(coords[0] as num).toDouble(),
|
||||
);
|
||||
}).toList();
|
||||
} 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");
|
||||
@@ -64,11 +112,12 @@ class Zone {
|
||||
isActive: json['isActive'] ?? false,
|
||||
speedLimit: json['speedLimit'] ?? '',
|
||||
shapeType: shapeType,
|
||||
points: points,
|
||||
geometry: parsedGeometry,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Zone{id: $id, title: $title, type: $type, points: $points}';
|
||||
return 'Zone{id: $id, title: $title, type: $type, polygonsCount: ${geometry.length}}';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user