Initial commit: SIBU 2.0 MISSION
This commit is contained in:
203
old/lib/models/bus_stop_model.dart
Normal file
203
old/lib/models/bus_stop_model.dart
Normal file
@ -0,0 +1,203 @@
|
||||
class BusStopModel {
|
||||
final String id;
|
||||
final String name;
|
||||
final double lat;
|
||||
final double lng;
|
||||
final String? city;
|
||||
final String? address;
|
||||
final String? parentId;
|
||||
final String? side;
|
||||
final String stopType;
|
||||
final bool hasShelter;
|
||||
final bool hasSeating;
|
||||
final bool isAccessible;
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
// Route-specific fields (from route_stops junction table)
|
||||
final int? stopOrder;
|
||||
final int? travelTimeMinutes;
|
||||
final bool? isPickupPoint;
|
||||
final bool? isDropoffPoint;
|
||||
|
||||
BusStopModel({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.lat,
|
||||
required this.lng,
|
||||
this.city,
|
||||
this.address,
|
||||
this.parentId,
|
||||
this.side,
|
||||
this.stopType = 'regular',
|
||||
this.hasShelter = false,
|
||||
this.hasSeating = false,
|
||||
this.isAccessible = false,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.stopOrder,
|
||||
this.travelTimeMinutes,
|
||||
this.isPickupPoint,
|
||||
this.isDropoffPoint,
|
||||
});
|
||||
|
||||
factory BusStopModel.fromJson(Map<String, dynamic> json) {
|
||||
return BusStopModel(
|
||||
id: json['id']?.toString() ?? '',
|
||||
name: json['name']?.toString() ?? '',
|
||||
lat: double.tryParse(json['lat']?.toString() ?? '0') ?? 0.0,
|
||||
lng: double.tryParse(json['lng']?.toString() ?? '0') ?? 0.0,
|
||||
city: json['city']?.toString(),
|
||||
address: json['address']?.toString(),
|
||||
parentId: json['parent_id']?.toString(),
|
||||
side: json['side']?.toString(),
|
||||
stopType: json['stop_type']?.toString() ?? 'regular',
|
||||
hasShelter: json['has_shelter'] == true,
|
||||
hasSeating: json['has_seating'] == true,
|
||||
isAccessible: json['is_accessible'] == true,
|
||||
createdAt:
|
||||
json['created_at'] != null
|
||||
? DateTime.tryParse(json['created_at'].toString())
|
||||
: null,
|
||||
updatedAt:
|
||||
json['updated_at'] != null
|
||||
? DateTime.tryParse(json['updated_at'].toString())
|
||||
: null,
|
||||
stopOrder:
|
||||
json['stop_order'] != null
|
||||
? int.tryParse(json['stop_order'].toString())
|
||||
: null,
|
||||
travelTimeMinutes:
|
||||
json['travel_time_minutes'] != null
|
||||
? int.tryParse(json['travel_time_minutes'].toString())
|
||||
: null,
|
||||
isPickupPoint: json['is_pickup_point'] == true,
|
||||
isDropoffPoint: json['is_dropoff_point'] == true,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'lat': lat,
|
||||
'lng': lng,
|
||||
'city': city,
|
||||
'address': address,
|
||||
'parent_id': parentId,
|
||||
'side': side,
|
||||
'stop_type': stopType,
|
||||
'has_shelter': hasShelter,
|
||||
'has_seating': hasSeating,
|
||||
'is_accessible': isAccessible,
|
||||
'created_at': createdAt?.toIso8601String(),
|
||||
'updated_at': updatedAt?.toIso8601String(),
|
||||
'stop_order': stopOrder,
|
||||
'travel_time_minutes': travelTimeMinutes,
|
||||
'is_pickup_point': isPickupPoint,
|
||||
'is_dropoff_point': isDropoffPoint,
|
||||
};
|
||||
}
|
||||
|
||||
// Helper getters
|
||||
String get displayName => name;
|
||||
|
||||
String get fullAddress {
|
||||
if (address != null && address!.isNotEmpty) {
|
||||
return city != null ? '$address, $city' : address!;
|
||||
}
|
||||
return city ?? 'Ubicación desconocida';
|
||||
}
|
||||
|
||||
String get stopTypeDisplay {
|
||||
switch (stopType) {
|
||||
case 'terminal':
|
||||
return 'Terminal';
|
||||
case 'express_only':
|
||||
return 'Solo Express';
|
||||
case 'regular':
|
||||
default:
|
||||
return 'Parada Regular';
|
||||
}
|
||||
}
|
||||
|
||||
List<String> get amenities {
|
||||
List<String> amenityList = [];
|
||||
if (hasShelter) amenityList.add('Refugio');
|
||||
if (hasSeating) amenityList.add('Asientos');
|
||||
if (isAccessible) amenityList.add('Accesible');
|
||||
return amenityList;
|
||||
}
|
||||
|
||||
String get amenitiesText {
|
||||
final amenityList = amenities;
|
||||
if (amenityList.isEmpty) return 'Sin servicios especiales';
|
||||
return amenityList.join(', ');
|
||||
}
|
||||
|
||||
bool get isTerminal => stopType == 'terminal';
|
||||
bool get isExpressOnly => stopType == 'express_only';
|
||||
|
||||
String get travelTimeText {
|
||||
if (travelTimeMinutes != null && travelTimeMinutes! > 0) {
|
||||
return '${travelTimeMinutes} min';
|
||||
}
|
||||
return 'N/A';
|
||||
}
|
||||
|
||||
BusStopModel copyWith({
|
||||
String? id,
|
||||
String? name,
|
||||
double? lat,
|
||||
double? lng,
|
||||
String? city,
|
||||
String? address,
|
||||
String? parentId,
|
||||
String? side,
|
||||
String? stopType,
|
||||
bool? hasShelter,
|
||||
bool? hasSeating,
|
||||
bool? isAccessible,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
int? stopOrder,
|
||||
int? travelTimeMinutes,
|
||||
bool? isPickupPoint,
|
||||
bool? isDropoffPoint,
|
||||
}) {
|
||||
return BusStopModel(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
lat: lat ?? this.lat,
|
||||
lng: lng ?? this.lng,
|
||||
city: city ?? this.city,
|
||||
address: address ?? this.address,
|
||||
parentId: parentId ?? this.parentId,
|
||||
side: side ?? this.side,
|
||||
stopType: stopType ?? this.stopType,
|
||||
hasShelter: hasShelter ?? this.hasShelter,
|
||||
hasSeating: hasSeating ?? this.hasSeating,
|
||||
isAccessible: isAccessible ?? this.isAccessible,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
stopOrder: stopOrder ?? this.stopOrder,
|
||||
travelTimeMinutes: travelTimeMinutes ?? this.travelTimeMinutes,
|
||||
isPickupPoint: isPickupPoint ?? this.isPickupPoint,
|
||||
isDropoffPoint: isDropoffPoint ?? this.isDropoffPoint,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BusStopModel(id: $id, name: $name, city: $city, stopType: $stopType)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
return other is BusStopModel && other.id == id;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
}
|
||||
113
old/lib/models/coupon_model.dart
Normal file
113
old/lib/models/coupon_model.dart
Normal file
@ -0,0 +1,113 @@
|
||||
class CouponModel {
|
||||
final String id;
|
||||
final String businessName;
|
||||
final String title;
|
||||
final String description;
|
||||
final DateTime? validUntil;
|
||||
final String? imageUrl;
|
||||
final String category;
|
||||
final bool isActive;
|
||||
final DateTime createdAt;
|
||||
|
||||
CouponModel({
|
||||
required this.id,
|
||||
required this.businessName,
|
||||
required this.title,
|
||||
required this.description,
|
||||
this.validUntil,
|
||||
this.imageUrl,
|
||||
required this.category,
|
||||
required this.isActive,
|
||||
required this.createdAt,
|
||||
});
|
||||
|
||||
factory CouponModel.fromMap(Map<String, dynamic> map) {
|
||||
return CouponModel(
|
||||
id: map['id'] as String,
|
||||
businessName: map['business_name'] as String,
|
||||
title: map['title'] as String,
|
||||
description: map['description'] as String? ?? '',
|
||||
validUntil: map['valid_until'] != null
|
||||
? DateTime.parse(map['valid_until'])
|
||||
: null,
|
||||
imageUrl: map['image_url'] as String?,
|
||||
category: map['category'] as String,
|
||||
isActive: map['is_active'] as bool? ?? true,
|
||||
createdAt: DateTime.parse(map['created_at']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'id': id,
|
||||
'business_name': businessName,
|
||||
'title': title,
|
||||
'description': description,
|
||||
'valid_until': validUntil?.toIso8601String(),
|
||||
'image_url': imageUrl,
|
||||
'category': category,
|
||||
'is_active': isActive,
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
bool get isExpired {
|
||||
if (validUntil == null) return false;
|
||||
return DateTime.now().isAfter(validUntil!);
|
||||
}
|
||||
|
||||
bool get isExpiringSoon {
|
||||
if (validUntil == null) return false;
|
||||
final now = DateTime.now();
|
||||
final difference = validUntil!.difference(now).inDays;
|
||||
return difference <= 3 && difference >= 0;
|
||||
}
|
||||
|
||||
String get categoryDisplayName {
|
||||
switch (category.toLowerCase()) {
|
||||
case 'restaurantes':
|
||||
return 'Restaurantes';
|
||||
case 'tiendas':
|
||||
return 'Tiendas';
|
||||
case 'servicios':
|
||||
return 'Servicios';
|
||||
case 'entretenimiento':
|
||||
return 'Entretenimiento';
|
||||
case 'salud':
|
||||
return 'Salud';
|
||||
case 'belleza':
|
||||
return 'Belleza';
|
||||
default:
|
||||
return 'Otros';
|
||||
}
|
||||
}
|
||||
|
||||
String get validUntilFormatted {
|
||||
if (validUntil == null) return 'Sin fecha de vencimiento';
|
||||
return '${validUntil!.day.toString().padLeft(2, '0')}/${validUntil!.month.toString().padLeft(2, '0')}/${validUntil!.year}';
|
||||
}
|
||||
|
||||
CouponModel copyWith({
|
||||
String? id,
|
||||
String? businessName,
|
||||
String? title,
|
||||
String? description,
|
||||
DateTime? validUntil,
|
||||
String? imageUrl,
|
||||
String? category,
|
||||
bool? isActive,
|
||||
DateTime? createdAt,
|
||||
}) {
|
||||
return CouponModel(
|
||||
id: id ?? this.id,
|
||||
businessName: businessName ?? this.businessName,
|
||||
title: title ?? this.title,
|
||||
description: description ?? this.description,
|
||||
validUntil: validUntil ?? this.validUntil,
|
||||
imageUrl: imageUrl ?? this.imageUrl,
|
||||
category: category ?? this.category,
|
||||
isActive: isActive ?? this.isActive,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
);
|
||||
}
|
||||
}
|
||||
154
old/lib/models/route_model.dart
Normal file
154
old/lib/models/route_model.dart
Normal file
@ -0,0 +1,154 @@
|
||||
class RouteModel {
|
||||
final String id;
|
||||
final String name;
|
||||
final String? description;
|
||||
final String color;
|
||||
final String direction;
|
||||
final String? originCity;
|
||||
final String? destinationCity;
|
||||
final double? distanceKm;
|
||||
final int? estimatedDurationMinutes;
|
||||
final String status;
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
RouteModel({
|
||||
required this.id,
|
||||
required this.name,
|
||||
this.description,
|
||||
required this.color,
|
||||
required this.direction,
|
||||
this.originCity,
|
||||
this.destinationCity,
|
||||
this.distanceKm,
|
||||
this.estimatedDurationMinutes,
|
||||
this.status = 'active',
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
factory RouteModel.fromJson(Map<String, dynamic> json) {
|
||||
return RouteModel(
|
||||
id: json['id']?.toString() ?? '',
|
||||
name: json['name']?.toString() ?? '',
|
||||
description: json['description']?.toString(),
|
||||
color: json['color']?.toString() ?? '#FEE715',
|
||||
direction: json['direction']?.toString() ?? 'outbound',
|
||||
originCity: json['origin_city']?.toString(),
|
||||
destinationCity: json['destination_city']?.toString(),
|
||||
distanceKm: json['distance_km'] != null
|
||||
? double.tryParse(json['distance_km'].toString())
|
||||
: null,
|
||||
estimatedDurationMinutes: json['estimated_duration_minutes'] != null
|
||||
? int.tryParse(json['estimated_duration_minutes'].toString())
|
||||
: null,
|
||||
status: json['status']?.toString() ?? 'active',
|
||||
createdAt: json['created_at'] != null
|
||||
? DateTime.tryParse(json['created_at'].toString())
|
||||
: null,
|
||||
updatedAt: json['updated_at'] != null
|
||||
? DateTime.tryParse(json['updated_at'].toString())
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'color': color,
|
||||
'direction': direction,
|
||||
'origin_city': originCity,
|
||||
'destination_city': destinationCity,
|
||||
'distance_km': distanceKm,
|
||||
'estimated_duration_minutes': estimatedDurationMinutes,
|
||||
'status': status,
|
||||
'created_at': createdAt?.toIso8601String(),
|
||||
'updated_at': updatedAt?.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
// Helper getters
|
||||
String get displayName {
|
||||
if (name.isNotEmpty) return name;
|
||||
final od = [originCity, destinationCity]
|
||||
.where((e) => e != null && e.trim().isNotEmpty)
|
||||
.map((e) => e!.trim())
|
||||
.join(' – ');
|
||||
return od.isNotEmpty ? od : 'Route';
|
||||
}
|
||||
|
||||
String get routeDescription {
|
||||
if (description != null && description!.isNotEmpty) {
|
||||
return description!;
|
||||
}
|
||||
return 'Ruta $displayName';
|
||||
}
|
||||
|
||||
String get durationText {
|
||||
if (estimatedDurationMinutes != null) {
|
||||
if (estimatedDurationMinutes! >= 60) {
|
||||
final hours = estimatedDurationMinutes! ~/ 60;
|
||||
final minutes = estimatedDurationMinutes! % 60;
|
||||
return minutes > 0 ? '${hours}h ${minutes}min' : '${hours}h';
|
||||
}
|
||||
return '${estimatedDurationMinutes}min';
|
||||
}
|
||||
return 'N/A';
|
||||
}
|
||||
|
||||
String get distanceText {
|
||||
if (distanceKm != null) {
|
||||
return '${distanceKm!.toStringAsFixed(1)} km';
|
||||
}
|
||||
return 'N/A';
|
||||
}
|
||||
|
||||
bool get isActive => status == 'active';
|
||||
|
||||
RouteModel copyWith({
|
||||
String? id,
|
||||
String? name,
|
||||
String? description,
|
||||
String? color,
|
||||
String? direction,
|
||||
String? originCity,
|
||||
String? destinationCity,
|
||||
double? distanceKm,
|
||||
int? estimatedDurationMinutes,
|
||||
String? status,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
}) {
|
||||
return RouteModel(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
description: description ?? this.description,
|
||||
color: color ?? this.color,
|
||||
direction: direction ?? this.direction,
|
||||
originCity: originCity ?? this.originCity,
|
||||
destinationCity: destinationCity ?? this.destinationCity,
|
||||
distanceKm: distanceKm ?? this.distanceKm,
|
||||
estimatedDurationMinutes:
|
||||
estimatedDurationMinutes ?? this.estimatedDurationMinutes,
|
||||
status: status ?? this.status,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RouteModel(id: $id, name: $name, direction: $direction, status: $status)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
return other is RouteModel && other.id == id;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
}
|
||||
72
old/lib/models/route_stop_model.dart
Normal file
72
old/lib/models/route_stop_model.dart
Normal file
@ -0,0 +1,72 @@
|
||||
class RouteStopModel {
|
||||
final String id;
|
||||
final String routeId;
|
||||
final String stopId;
|
||||
final int stopOrder;
|
||||
final int? travelTimeMinutes;
|
||||
final bool isPickupPoint;
|
||||
final bool isDropoffPoint;
|
||||
final DateTime createdAt;
|
||||
|
||||
// Populated from joined data
|
||||
final String? stopName;
|
||||
final double? latitude;
|
||||
final double? longitude;
|
||||
final String? city;
|
||||
|
||||
RouteStopModel({
|
||||
required this.id,
|
||||
required this.routeId,
|
||||
required this.stopId,
|
||||
required this.stopOrder,
|
||||
this.travelTimeMinutes,
|
||||
required this.isPickupPoint,
|
||||
required this.isDropoffPoint,
|
||||
required this.createdAt,
|
||||
this.stopName,
|
||||
this.latitude,
|
||||
this.longitude,
|
||||
this.city,
|
||||
});
|
||||
|
||||
factory RouteStopModel.fromJson(Map<String, dynamic> json) {
|
||||
return RouteStopModel(
|
||||
id: json['id'] as String,
|
||||
routeId: json['route_id'] as String,
|
||||
stopId: json['stop_id'] as String,
|
||||
stopOrder: json['stop_order'] as int,
|
||||
travelTimeMinutes: json['travel_time_minutes'] as int?,
|
||||
isPickupPoint: json['is_pickup_point'] as bool,
|
||||
isDropoffPoint: json['is_dropoff_point'] as bool,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
stopName: json['stop_name'] as String?,
|
||||
latitude: json['latitude']?.toDouble(),
|
||||
longitude: json['longitude']?.toDouble(),
|
||||
city: json['city'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'route_id': routeId,
|
||||
'stop_id': stopId,
|
||||
'stop_order': stopOrder,
|
||||
'travel_time_minutes': travelTimeMinutes,
|
||||
'is_pickup_point': isPickupPoint,
|
||||
'is_dropoff_point': isDropoffPoint,
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
if (stopName != null) 'stop_name': stopName,
|
||||
if (latitude != null) 'latitude': latitude,
|
||||
if (longitude != null) 'longitude': longitude,
|
||||
if (city != null) 'city': city,
|
||||
};
|
||||
}
|
||||
|
||||
String get operationType {
|
||||
if (isPickupPoint && isDropoffPoint) return 'Subida/Bajada';
|
||||
if (isPickupPoint) return 'Solo Subida';
|
||||
if (isDropoffPoint) return 'Solo Bajada';
|
||||
return 'Sin servicio';
|
||||
}
|
||||
}
|
||||
140
old/lib/models/taxi_model.dart
Normal file
140
old/lib/models/taxi_model.dart
Normal file
@ -0,0 +1,140 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// Model representing a taxi service with contact and location information
|
||||
@immutable
|
||||
class TaxiModel {
|
||||
final String id;
|
||||
final String name;
|
||||
final String phone;
|
||||
final String corregimiento;
|
||||
final String shift;
|
||||
final bool isActive;
|
||||
final DateTime createdAt;
|
||||
final DateTime updatedAt;
|
||||
|
||||
const TaxiModel({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.phone,
|
||||
required this.corregimiento,
|
||||
required this.shift,
|
||||
required this.isActive,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
/// Create TaxiModel from Supabase JSON response
|
||||
factory TaxiModel.fromJson(Map<String, dynamic> json) {
|
||||
return TaxiModel(
|
||||
id: json['id'] as String,
|
||||
name: json['name'] as String,
|
||||
phone: json['phone'] as String,
|
||||
corregimiento: json['corregimiento'] as String,
|
||||
shift: json['shift'] as String,
|
||||
isActive: json['is_active'] as bool? ?? true,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
/// Convert TaxiModel to JSON for Supabase operations
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'phone': phone,
|
||||
'corregimiento': corregimiento,
|
||||
'shift': shift,
|
||||
'is_active': isActive,
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
'updated_at': updatedAt.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
/// Create a copy with modified properties
|
||||
TaxiModel copyWith({
|
||||
String? id,
|
||||
String? name,
|
||||
String? phone,
|
||||
String? corregimiento,
|
||||
String? shift,
|
||||
bool? isActive,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
}) {
|
||||
return TaxiModel(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
phone: phone ?? this.phone,
|
||||
corregimiento: corregimiento ?? this.corregimiento,
|
||||
shift: shift ?? this.shift,
|
||||
isActive: isActive ?? this.isActive,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
return other is TaxiModel && other.id == id;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TaxiModel(id: $id, name: $name, phone: $phone, corregimiento: $corregimiento, shift: $shift, isActive: $isActive)';
|
||||
}
|
||||
}
|
||||
|
||||
/// Model representing a user's favorite taxi
|
||||
@immutable
|
||||
class FavoriteTaxiModel {
|
||||
final String id;
|
||||
final String userId;
|
||||
final String taxiId;
|
||||
final DateTime createdAt;
|
||||
|
||||
const FavoriteTaxiModel({
|
||||
required this.id,
|
||||
required this.userId,
|
||||
required this.taxiId,
|
||||
required this.createdAt,
|
||||
});
|
||||
|
||||
/// Create FavoriteTaxiModel from Supabase JSON response
|
||||
factory FavoriteTaxiModel.fromJson(Map<String, dynamic> json) {
|
||||
return FavoriteTaxiModel(
|
||||
id: json['id'] as String,
|
||||
userId: json['user_id'] as String,
|
||||
taxiId: json['taxi_id'] as String,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
/// Convert FavoriteTaxiModel to JSON for Supabase operations
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'user_id': userId,
|
||||
'taxi_id': taxiId,
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
return other is FavoriteTaxiModel && other.id == id;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'FavoriteTaxiModel(id: $id, userId: $userId, taxiId: $taxiId)';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user