diff --git a/lib/models/service.dart b/lib/models/service.dart index e945695..bb5beca 100644 --- a/lib/models/service.dart +++ b/lib/models/service.dart @@ -41,7 +41,22 @@ class Service { required this.location, }); + static const _statusMap = { + 'pending': 0, 'accepted': 1, 'denied': 2, 'active': 3, + 'cancelled': 4, 'completed': 5, 'self_booked': 6, + }; + static Service fromJson(Map doc, String id) { + final rawStatus = doc['status']; + final statusInt = rawStatus is int ? rawStatus + : rawStatus is String ? (_statusMap[rawStatus] ?? 0) + : (rawStatus as num?)?.toInt() ?? 0; + + final rawLoc = doc['location_preference'] ?? doc['location']; + final locInt = rawLoc == 'delivery' ? 1 + : rawLoc == 'office' ? 0 + : (rawLoc as num?)?.toInt() ?? 0; + return Service( id: id, professionalId: doc['professional_id'] as String, @@ -49,17 +64,27 @@ class Service { userId: doc['user_id'] as String, userScored: doc['user_scored'] as bool? ?? false, address: doc['address'] as String? ?? '', - aditionalAddress: doc['aditional_address'] as String? ?? '', + aditionalAddress: (doc['additional_address'] ?? doc['aditional_address']) as String? ?? '', latitude: (doc['latitude'] as num?)?.toDouble() ?? 0.0, longitude: (doc['longitude'] as num?)?.toDouble() ?? 0.0, - day: doc['day'] as String? ?? '', + day: doc['day']?.toString() ?? '', createdAt: doc['created_at']?.toString() ?? '', description: doc['description'] as String? ?? '', - range1Hour1: parseTimeOfDay(doc['range1_hour1'] as String? ?? '0:0'), - range1Hour2: parseTimeOfDay(doc['range1_hour2'] as String? ?? '0:0'), - status: intToEnumService((doc['status'] as num?)?.toInt() ?? 0), - rate: doc['rate'] as String? ?? '', - location: intToEnum((doc['location'] as num?)?.toInt() ?? 0), + range1Hour1: _parseTime(doc['range1_hour1']?.toString() ?? '0:0'), + range1Hour2: _parseTime(doc['range1_hour2']?.toString() ?? '0:0'), + status: intToEnumService(statusInt), + rate: doc['rate']?.toString() ?? '', + location: intToEnum(locInt), + ); + } + + static TimeOfDay _parseTime(String t) { + // Handle ISO8601 (e.g. "1970-01-01T08:30:00.000Z") or "H:M" + final s = t.contains('T') ? t.split('T')[1] : t; + final parts = s.split(':'); + return TimeOfDay( + hour: int.tryParse(parts[0]) ?? 0, + minute: int.tryParse(parts.length > 1 ? parts[1] : '0') ?? 0, ); } @@ -85,10 +110,7 @@ class Service { }; } - static TimeOfDay parseTimeOfDay(String timeString) { - final parts = timeString.split(':'); - return TimeOfDay(hour: int.parse(parts[0]), minute: int.parse(parts[1])); - } + static TimeOfDay parseTimeOfDay(String timeString) => _parseTime(timeString); String? formatTimeOfDay(TimeOfDay? time) { if (time != null) return '${time.hour}:${time.minute}'; diff --git a/lib/providers/calendar_services_provider.dart b/lib/providers/calendar_services_provider.dart index 7ec5a56..c02a35b 100644 --- a/lib/providers/calendar_services_provider.dart +++ b/lib/providers/calendar_services_provider.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:prosapp_web_app/models/pro_state.dart'; import 'package:prosapp_web_app/models/service.dart'; import 'package:prosapp_web_app/models/servicio_profesional.dart'; import 'package:prosapp_web_app/models/usuario.dart'; @@ -20,7 +21,10 @@ class CalendarServicesProvider extends ChangeNotifier { getServicesForProfessional(String userId) async { try { isLoading = true; - final data = await _api.get('/services/professional/calendar') as List; + final res = await _api.get('/services/professional/calendar'); + final data = (res is Map ? res['data'] : res) as List; + + // Fetch users for calendar entries (calendar endpoint returns flat list without embedded users) final servicios = data.map((e) { final m = e as Map; return Service.fromJson(m, m['id'] as String); @@ -34,7 +38,11 @@ class CalendarServicesProvider extends ChangeNotifier { final usersMap = {for (var u in users) u.id: u}; services = servicios - .map((s) => ServicioProfesional(user: usersMap[s.userId]!, service: s)) + .map((s) => ServicioProfesional( + user: usersMap[s.userId] ?? Usuario(id: s.userId, email: null, phone: null, name: '?', + nickname: null, city: null, picture: null, birthday: null, gender: null, + proState: ProState.inactive, token: null), + service: s)) .toList() ..sort((a, b) { final dateA = DateTime.parse(a.service.day); diff --git a/lib/providers/services_provider.dart b/lib/providers/services_provider.dart index fedca3d..fee7f5b 100644 --- a/lib/providers/services_provider.dart +++ b/lib/providers/services_provider.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:prosapp_web_app/models/service.dart'; import 'package:prosapp_web_app/models/service_status.dart'; import 'package:prosapp_web_app/models/servicio_profesional.dart'; +import 'package:prosapp_web_app/models/pro_state.dart'; import 'package:prosapp_web_app/models/usuario.dart'; import 'package:prosapp_web_app/services/api_service.dart'; @@ -97,27 +98,36 @@ class ServicesProvider extends ChangeNotifier { Future _loadServices(String path, {required bool forUser}) async { try { isLoading = true; - final data = await _api.get(path) as List; - final servicios = data.map((e) { + final res = await _api.get(path); + // All service endpoints return {data:[...], meta:{...}} + final data = (res is Map ? res['data'] : res) as List; + + services = data.map((e) { final m = e as Map; - return Service.fromJson(m, m['id'] as String); - }).toList(); - - final ids = servicios.map((s) => forUser ? s.professionalId : s.userId).toSet().toList(); - final users = await Future.wait(ids.map((id) async { - final u = await _api.get('/users/$id'); - return Usuario.fromDocument(u as Map); - })); - final usersMap = {for (var u in users) u.id: u}; - - services = servicios.map((s) { - final userId = forUser ? s.professionalId : s.userId; - return ServicioProfesional(user: usersMap[userId]!, service: s); + final servicio = Service.fromJson(m, m['id'] as String); + // User data is embedded in the response to avoid extra calls + // forUser=true: professional's user is in m['professionals']['users'] + // forUser=false: client's user is in m['users'] + Map? userDoc; + if (forUser) { + final prof = m['professionals'] as Map?; + userDoc = prof?['users'] as Map?; + } else { + userDoc = m['users'] as Map?; + } + final user = userDoc != null + ? Usuario.fromDocument(userDoc) + : Usuario(id: '', email: null, phone: null, name: '?', nickname: null, + city: null, picture: null, birthday: null, gender: null, + proState: ProState.inactive, token: null); + return ServicioProfesional(user: user, service: servicio); }).toList() ..sort((a, b) { - final dateA = DateTime.parse(a.service.day); - final dateB = DateTime.parse(b.service.day); - if (dateA != dateB) return dateA.compareTo(dateB); + try { + final dateA = DateTime.parse(a.service.day); + final dateB = DateTime.parse(b.service.day); + if (dateA != dateB) return dateA.compareTo(dateB); + } catch (_) {} final tA = a.service.range1Hour1.hour * 60 + a.service.range1Hour1.minute; final tB = b.service.range1Hour1.hour * 60 + b.service.range1Hour1.minute; return tA.compareTo(tB);