bookmywages/lib/view/auth/auth_repository.dart
2025-10-16 11:21:52 +05:30

1871 lines
58 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:bookmywages/model/Banner_model.dart';
import 'package:bookmywages/model/Booking_model.dart';
import 'package:bookmywages/model/Categories_model.dart';
import 'package:bookmywages/model/detail_page_model.dart';
import 'package:bookmywages/model/enquriy_list_model.dart';
import 'package:bookmywages/model/enquriy_model.dart';
import 'package:bookmywages/model/expired_plan_model.dart';
import 'package:bookmywages/model/get_review_model.dart';
import 'package:bookmywages/model/login_model.dart';
import 'package:bookmywages/model/most_popular_model.dart';
import 'package:bookmywages/model/notification_model.dart';
import 'package:bookmywages/model/otp_model.dart';
import 'package:bookmywages/model/package_model.dart';
import 'package:bookmywages/model/payment_details_model.dart';
import 'package:bookmywages/model/profile_get_model.dart';
import 'package:bookmywages/model/service_model.dart';
import 'package:bookmywages/model/subcategory_model.dart';
import 'package:bookmywages/model/user_booking_details.dart'
show UserBookingDetails;
import 'package:bookmywages/model/vendor_model/terms_and_conditions_model.dart';
import 'package:bookmywages/model/vendor_model/vendor_booking_model.dart';
import 'package:bookmywages/model/vendor_model/vendor_catgories_model.dart'
show VendorCategoriesModel;
import 'package:bookmywages/model/vendor_model/vendor_profile_model.dart';
import 'package:bookmywages/model/vendor_model/vendor_service_model.dart';
import 'package:bookmywages/model/vendor_model/vendor_serviceupload_model.dart';
import 'package:bookmywages/model/vendor_model/vendorregister_model.dart';
import 'package:bookmywages/viewmodel/consts_api.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http_parser/http_parser.dart'; // Add this at the top
class AuthRepository {
Future<Map<String, dynamic>> loginUser(
String url,
LoginModel loginModel,
) async {
try {
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode(loginModel.toJson()),
);
if (response.statusCode == 200) {
final decoded = jsonDecode(response.body);
print('Decoded Response: $decoded'); // Debug print
dynamic data = decoded['data'];
String userId = '';
String isverify = '';
// Handle different response structures
if (data is List && data.isNotEmpty) {
// Response contains a list of data
userId = data[0]['id']?.toString() ?? '';
isverify = data[0]['is_verified']?.toString() ?? '';
} else if (data is Map) {
// Response contains a single data object
userId = data['id']?.toString() ?? '';
isverify = data['is_verified']?.toString() ?? '';
// Check if vendor_id exists in the data map
} else {
throw Exception('Unexpected response structure: $data');
}
// Store both values in SharedPreferences
final prefs = await SharedPreferences.getInstance();
await prefs.setString('userId', userId);
await prefs.setString('is_verified', isverify);
// Also store the full data JSON string for other operations
await prefs.setString('data', userId);
return decoded;
} else {
throw Exception(
'Login failed with status code ${response.statusCode}: ${response.body}',
);
}
} catch (e) {
print('Login error: $e');
throw Exception('Login failed: $e');
}
}
Future<Map<String, dynamic>> registerUser(
String url,
Map<String, dynamic> data,
) async {
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode(data),
);
if (response.statusCode == 200) {
final decoded = jsonDecode(response.body);
print('Decoded Response: $decoded'); // Debug print
dynamic data = decoded['data'];
String userId;
String isverify;
if (data is List && data.isNotEmpty) {
userId = data[0]['id'].toString();
isverify = data[0]['is_verified'].toString();
} else if (data is Map && data.containsKey('id')) {
userId = data['id'].toString();
isverify = data['is_verified'].toString();
} else {
throw Exception('Unexpected response structure: $data');
}
final prefs = await SharedPreferences.getInstance();
await prefs.setString('userId', userId);
await prefs.setString('is_verified', isverify);
return decoded;
} else {
throw Exception('Register failed: ${response.body}');
}
}
// Add to AuthRepository class
Future<Map<String, dynamic>> verifyOtp(String url, OtpModel otpModel) async {
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode(otpModel.toJson()),
);
if (response.statusCode == 200) {
final decoded = jsonDecode(response.body);
print('OTP Verify Response: $decoded');
// Directly store is_verified = '1'
final prefs = await SharedPreferences.getInstance();
await prefs.setString('is_verified', '1');
return decoded;
} else {
throw Exception('OTP verification failed: ${response.body}');
}
}
}
class BannerRepository {
Future<List<BannerModel>> fetchBanners(String url) async {
try {
final response = await http
.get(Uri.parse(url))
.timeout(const Duration(seconds: 10));
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> bannerList = jsonBody['data'] ?? [];
return bannerList.map((json) => BannerModel.fromJson(json)).toList();
} else {
return []; // return empty list on server error
}
} catch (_) {
return []; // return empty list on timeout or any error
}
}
}
class CategoryRepository {
Future<List<CategoriesModel>> fetchCategories(String url) async {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> categoryList = jsonBody['data'] ?? [];
return categoryList
.map((json) => CategoriesModel.fromJson(json))
.toList();
} else {
throw Exception('Failed to load categories');
}
}
}
class packageRepository {
Future<List<PackageModel>> fetchpackage(String url) async {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> packagelist = jsonBody['data'] ?? [];
return packagelist.map((json) => PackageModel.fromJson(json)).toList();
} else {
throw Exception('Failed to load categories');
}
}
}
class SubcategoryRepository {
Future<List<SubcategoryModel>> fetchSubcategories(
String url,
String categoryId,
) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'userId': userId, 'category': categoryId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> list = jsonBody['data'] ?? [];
return list.map((e) => SubcategoryModel.fromJson(e)).toList();
} else {
throw Exception('Failed to load subcategories');
}
}
}
class ProfilegetRepository {
Future<List<ProfileGetModel>> fetchprofileget(String url) async {
// Retrieve userId from SharedPreferences
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
// Debugging: Print the userId to make sure it's correct
print('User ID: $userId');
// Check if userId is available before making the request
if (userId.isEmpty) {
throw Exception('User ID is not available.');
}
// Send the userId in the API request
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId}),
);
// Check if the response status code is successful
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> list = jsonBody['data'] ?? [];
// Convert the JSON response to a list of ProfileGetModel objects
return list.map((e) => ProfileGetModel.fromJson(e)).toList();
} else {
// Handle API errors
throw Exception(
'Failed to load profile data, status code: ${response.statusCode}',
);
}
}
}
class ServiceRepository {
Future<List<ServiceModel>> fetchService(
String url,
String categoryId, [
String? subcategoryId,
String? selecttype, // Optional parameter in square brackets
]) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
// Create the request body
Map<String, dynamic> requestBody = {
'user_id': userId,
'category': categoryId,
};
// Add subcategory only if it's provided
if (subcategoryId != null && subcategoryId.isNotEmpty) {
requestBody['subcategory'] = subcategoryId;
}
if (selecttype != null && selecttype.isNotEmpty) {
requestBody['service_type'] = selecttype;
}
print('Request Body: $requestBody'); // Debug log
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode(requestBody),
);
if (response.statusCode == 200) {
print('Response: ${response.body}'); // Debug log
final jsonBody = jsonDecode(response.body);
final List<dynamic> list = jsonBody['data'] ?? [];
return list.map((e) => ServiceModel.fromJson(e)).toList();
} else {
throw Exception('Failed to load services: ${response.statusCode}');
}
}
}
class ProfileupdateRepository {
Future<List<ProfileGetModel>> fetchprofileupdate(String url) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
if (userId.isEmpty) throw Exception('User ID is not available.');
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> list = jsonBody['data'] ?? [];
return list.map((e) => ProfileGetModel.fromJson(e)).toList();
} else {
throw Exception('Failed to load profile, code: ${response.statusCode}');
}
}
Future<void> updateProfile({
required String url,
required String name,
required String number,
required String email,
required String address,
File? imageFile,
}) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
final request = http.MultipartRequest('POST', Uri.parse(url));
request.fields['user_id'] = userId;
request.fields['name'] = name;
request.fields['number'] = number;
request.fields['email'] = email;
request.fields['address'] = address;
if (imageFile != null) {
request.files.add(
await http.MultipartFile.fromPath(
'profile_pic', // Make sure this matches your backend key
imageFile.path,
contentType: MediaType('image', 'jpeg'), // Optional but recommended
),
);
}
final response = await request.send();
if (response.statusCode != 200) {
throw Exception('Failed to update profile');
}
}
}
class GetReviewRepository {
Future<List<GetReviewModel>> fetchgetreview(
String url,
String serviceId,
) async {
Map<String, dynamic> requestBody = {'service_id': serviceId};
print('Request Body: $requestBody');
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode(requestBody),
);
if (response.statusCode == 200) {
print('Response: ${response.body}');
final jsonBody = jsonDecode(response.body);
final List<dynamic> list = jsonBody['data'] ?? [];
return list.map((e) => GetReviewModel.fromJson(e)).toList();
} else {
throw Exception('Failed to load reviews: ${response.statusCode}');
}
}
}
class MostPopularRepository {
Future<List<MostPopularModel>> fetchMostPopular(
String url,
String categoryId,
) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
Map<String, dynamic> requestBody = {
'user_id': userId,
'category': categoryId,
};
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode(requestBody),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> list = jsonBody['data'] ?? [];
return list.map((e) => MostPopularModel.fromJson(e)).toList();
} else {
throw Exception('Failed to load services: ${response.statusCode}');
}
}
}
class EnquriyRepository {
Future<List<EnquiryModel>> fetchenquriy(String url) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
if (userId.isEmpty) throw Exception('User ID is not available.');
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> list = jsonBody['data'] ?? [];
return list.map((e) => EnquiryModel.fromJson(e)).toList();
} else {
throw Exception('Failed to load profile, code: ${response.statusCode}');
}
}
Future<void> updateEnquriy({
required BuildContext context,
required String url,
required String name,
required String number,
required String email,
required String message,
required String serviceid,
}) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
final request = http.MultipartRequest('POST', Uri.parse(url));
request.fields['user_id'] = userId;
request.fields['name'] = name;
request.fields['mobile'] = number;
request.fields['email'] = email;
request.fields['message'] = message;
request.fields['service_id'] = serviceid;
final response = await request.send();
if (response.statusCode == 200) {
Fluttertoast.showToast(
msg: "Enquiry Successful",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
);
} else {
Fluttertoast.showToast(
msg: "Failed to update profile",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
);
throw Exception('Failed to update profile');
}
}
}
class BookingRepository {
Future<List<BookingModel>> fetchBooking(String url) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
if (userId.isEmpty) throw Exception('User ID is not available.');
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> list = jsonBody['data'] ?? [];
return list.map((e) => BookingModel.fromJson(e)).toList();
} else {
throw Exception(
'Failed to load booking data. Code: ${response.statusCode}',
);
}
}
Future<void> updateBooking({
required BuildContext context,
required String url,
required String name,
required String number,
required String email,
required String message,
required String address,
required String date,
required String time,
required String serviceId,
}) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
if (userId.isEmpty) {
Fluttertoast.showToast(
msg: "User ID not found",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
);
return;
}
final request = http.MultipartRequest('POST', Uri.parse(url));
request.fields['user_id'] = userId;
request.fields['name'] = name;
request.fields['mobile_number'] = number;
request.fields['email'] = email;
request.fields['message'] = message;
request.fields['service_id'] = serviceId;
request.fields['address'] = address;
request.fields['service_date'] = date;
request.fields['service_time'] = time;
final response = await request.send();
final responseBody = await response.stream.bytesToString();
final jsonResponse = jsonDecode(responseBody);
if (response.statusCode == 200) {
Fluttertoast.showToast(
msg: "Booking Successful",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
);
} else if (response.statusCode == 404 &&
jsonResponse['data'] == 'You can book maximum 1 services.') {
Fluttertoast.showToast(
msg: jsonResponse['data'],
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
);
} else {
Fluttertoast.showToast(
msg:
jsonResponse['data'] ??
'Failed to submit enquiry. Code: ${response.statusCode}',
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
);
throw Exception('Failed to update booking');
}
}
}
// ignore: camel_case_types
class updatereviewRepository {
Future<List<GetReviewModel>> updatereview(String url) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
if (userId.isEmpty) throw Exception('User ID is not available.');
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> list = jsonBody['data'] ?? [];
return list.map((e) => GetReviewModel.fromJson(e)).toList();
} else {
throw Exception(
'Failed to load booking data. Code: ${response.statusCode}',
);
}
}
Future<void> updatereviews({
required BuildContext context,
required String url,
required String review,
required String serviceId,
}) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
if (userId.isEmpty) {
Fluttertoast.showToast(
msg: "User ID not found",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
);
return;
}
final request = http.MultipartRequest('POST', Uri.parse(url));
request.fields['user_id'] = userId;
request.fields['review'] = review;
request.fields['service_id'] = serviceId;
final response = await request.send();
final responseBody = await response.stream.bytesToString();
final jsonResponse = jsonDecode(responseBody);
if (response.statusCode == 200) {
Fluttertoast.showToast(
msg: "Review submitted successfully",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.green,
textColor: Colors.white,
);
} else {
Fluttertoast.showToast(
msg:
jsonResponse['data'] ??
'Failed to submit review. Code: ${response.statusCode}',
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.red,
textColor: Colors.white,
);
throw Exception('Failed to update review');
}
}
}
class enquriylistRepository {
Future<List<EnquiryListModel>> fetchenquirylist(String url) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
if (userId.isEmpty) throw Exception('User ID is not available.');
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> list = jsonBody['data'] ?? [];
return list.map((e) => EnquiryListModel.fromJson(e)).toList();
} else {
throw Exception(
'Failed to load booking data. Code: ${response.statusCode}',
);
}
}
}
class EnquriydeleteRepository {
Future<bool> enquriydelete(String url, String id) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId, 'id': id}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
// Assuming your API returns a success flag or message
// Adjust this based on your actual API response
return jsonBody['success'] == true ||
jsonBody['status'] == 'success' ||
jsonBody['message']?.toLowerCase().contains('success') == true;
} else {
throw Exception('Failed to delete enquiry');
}
}
}
class PaymentdetailsRepository {
Future<List<PaymentDetailsModel>> fetchpayment(String url) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> dataList = jsonBody['data'] ?? [];
return dataList
.map((json) => PaymentDetailsModel.fromJson(json))
.toList();
} else {
throw Exception('Failed to fetch payment details');
}
}
}
class PaymentdeleteRepository {
Future<bool> paymentdelete(String url, String id) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId, 'id': id}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
// Assuming your API returns a success flag or message
// Adjust this based on your actual API response
return jsonBody['success'] == true ||
jsonBody['status'] == 'success' ||
jsonBody['message']?.toLowerCase().contains('success') == true;
} else {
throw Exception('Failed to delete payment Details');
}
}
}
class ChangepasswordRepository {
Future<bool> changepassword(String url, String password) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId, 'password': password}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
// Assuming your API returns a success flag or message
// Adjust this based on your actual API response
return jsonBody['success'] == true ||
jsonBody['status'] == 'success' ||
jsonBody['message']?.toLowerCase().contains('success') == true;
} else {
throw Exception('Failed to changepassword');
}
}
}
class UserhistoryBookingdetailsRepository {
Future<List<UserBookingDetails>> fetchhistorybooking(String url) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
print(response.body);
print(jsonBody);
final List<dynamic> dataList = jsonBody['data'] ?? [];
return dataList.map((json) => UserBookingDetails.fromJson(json)).toList();
} else {
throw Exception('Failed to fetch payment details');
}
}
}
class CancelbookingRepository {
Future<bool> cancelbooking({
required String url,
required String id,
required String serviceId,
required String type,
}) async {
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'id': id, 'service_id': serviceId, 'type': type}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
return jsonBody['success'] == true ||
jsonBody['status'] == 'success' ||
jsonBody['message']?.toLowerCase().contains('success') == true;
} else {
throw Exception('Failed to cancel booking');
}
}
}
class BookingmodifyRepository {
Future<bool> bookingmodify({
required String url,
required String id,
required String serviceId,
required String servicedate,
required String servicetime,
}) async {
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'id': id,
'service_id': serviceId,
'service_date': servicedate,
'service_time': servicetime,
}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
return jsonBody['success'] == true ||
jsonBody['status'] == 'success' ||
jsonBody['message']?.toLowerCase().contains('success') == true;
} else {
throw Exception('Failed to modify');
}
}
}
class ExpiredPlanRepository {
Future<ExpiredPlanModel> fetchExpiredPlan(String url) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final Map<String, dynamic> data = jsonBody['data'] ?? {};
return ExpiredPlanModel.fromJson(data);
} else {
throw Exception('Failed to fetch expired plan');
}
}
}
class PlanSuccessRepository {
Future<bool> planSuccess({
required String url,
required String userId,
required String planId,
required int duration,
required int type,
}) async {
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'user_id': userId,
'plan_id': planId,
'duration': duration.toString(),
'type': type.toString(),
}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
return jsonBody['success'] == true ||
jsonBody['status'] == 'success' ||
jsonBody['message']?.toLowerCase().contains('success') == true;
} else {
throw Exception('Failed to subscribe to plan');
}
}
}
////vendor flow
class GetvendorId {
Future fetchGetid(String url) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final data = jsonBody['data'];
// Extract and store vendor_id and vendor_status if not null
if (data != null) {
final vendorId = data['vendor_id']?.toString() ?? '';
final vendorStatus = data['vendor_status']?.toString() ?? '';
await prefs.setString('vendor_id', vendorId);
await prefs.setString('vendor_status', vendorStatus);
print('Stored vendor_id: $vendorId');
print('Stored vendor_status: $vendorStatus');
}
return data;
} else {
throw Exception('Failed to fetch vendor data');
}
}
}
class VendorRegister {
Future<Map<String, dynamic>> vendorRegister(
String url,
VendorRegisterModel vendorModel,
) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
vendorModel.userId = userId; // inject userId into the model
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode(vendorModel.toJson()),
);
if (response.statusCode == 200) {
final decoded = jsonDecode(response.body);
print('Decoded Response: $decoded');
return decoded;
} else {
throw Exception('Register failed: ${response.body}');
}
}
}
class VendorGetProfile {
Future<Map<String, dynamic>> vendorGetProfile(String url) async {
try {
final prefs = await SharedPreferences.getInstance();
final dataId = prefs.getString('vendor_id') ?? '';
if (dataId.isEmpty) {
throw Exception('Data ID not found in SharedPreferences.');
}
final body = jsonEncode({'dataId': dataId});
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: body,
);
if (response.statusCode == 200) {
final decoded = jsonDecode(response.body);
print('Decoded Response: $decoded');
return decoded; // Return the decoded response directly
} else {
throw Exception(
'Get profile failed with status ${response.statusCode}: ${response.body}',
);
}
} catch (e) {
print('Error in vendorGetProfile: $e');
rethrow;
}
}
}
class Vendorserviceupload {
Future<Map<String, dynamic>> vendorserviceupload(
String url,
VendorServiceUploadModel serviceupload,
List<File> images,
) async {
try {
// Create a multipart request for uploading files and data
var request = http.MultipartRequest('POST', Uri.parse(url));
// Add service data as fields
request.fields['vendor_id'] = serviceupload.id;
request.fields['vendorname'] = serviceupload.vendorName;
request.fields['servicename'] = serviceupload.serviceName;
request.fields['service_type'] = serviceupload.serviceType;
request.fields['category'] = serviceupload.category;
request.fields['subcategory'] = serviceupload.subcategory;
request.fields['workinghours'] = serviceupload.workingHours;
request.fields['workingduration'] = serviceupload.workingDuration;
request.fields['amount'] = serviceupload.amount.toString();
request.fields['location'] = serviceupload.location;
request.fields['description'] = serviceupload.description ?? '';
request.fields['details'] = serviceupload.details;
// Add video links as JSON array
if (serviceupload.videos.isNotEmpty) {
request.fields['videos'] = jsonEncode(serviceupload.videos);
}
// Add images as files with array notation
for (int i = 0; i < images.length; i++) {
final file = images[i];
final fileName =
'image_${i}_${DateTime.now().millisecondsSinceEpoch}.jpg';
// Get file extension from path
String extension = file.path.split('.').last.toLowerCase();
String mimeType = 'image/jpeg'; // Default
// Set correct mime type based on extension
if (extension == 'png') {
mimeType = 'image/png';
} else if (extension == 'jpg' || extension == 'jpeg') {
mimeType = 'image/jpeg';
} else if (extension == 'gif') {
mimeType = 'image/gif';
} else if (extension == 'webp') {
mimeType = 'image/webp';
}
// Add the file to the request with indexed array notation
request.files.add(
http.MultipartFile(
'images[$i]', // Indexed array notation for multiple images
file.readAsBytes().asStream(),
file.lengthSync(),
filename: fileName,
contentType: MediaType.parse(mimeType),
),
);
}
// Send the request
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
// Parse response regardless of status code
try {
final decoded = jsonDecode(response.body) as Map<String, dynamic>;
print('Decoded Response: $decoded');
// Check if request was successful
if (response.statusCode == 200 || response.statusCode == 201) {
return decoded;
} else {
// For failed requests, extract error message
String errorMessage =
decoded['data']?.toString() ??
decoded['message']?.toString() ??
'Upload failed with status: ${response.statusCode}';
// Return the error response for handling upstream
return {
'success': false,
'error': errorMessage,
'statusCode': response.statusCode,
'data': decoded,
};
}
} catch (jsonError) {
// If JSON parsing fails, use raw response
String errorMessage =
'Request failed with status: ${response.statusCode}. Response: ${response.body}';
Fluttertoast.showToast(
msg: 'Server response error',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
);
throw Exception(errorMessage);
}
} on SocketException catch (e) {
String errorMessage = 'No internet connection: ${e.message}';
Fluttertoast.showToast(
msg: 'No internet connection',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
);
throw Exception(errorMessage);
} on http.ClientException catch (e) {
String errorMessage = 'Network error: ${e.message}';
Fluttertoast.showToast(
msg: 'Network error occurred',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
);
throw Exception(errorMessage);
} on FormatException catch (e) {
String errorMessage = 'Invalid response format: ${e.message}';
Fluttertoast.showToast(
msg: 'Invalid server response',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
);
throw Exception(errorMessage);
} catch (e) {
String errorMessage = 'Unexpected error: $e';
Fluttertoast.showToast(
msg: 'Something went wrong',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
);
throw Exception(errorMessage);
}
}
}
class VendorbookingdetailsRepository {
Future<List<VendorBookingModel>> fetchvendorbooking(String url) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('vendor_id') ?? '';
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'vendor_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
print(response.body);
print(jsonBody);
final List<dynamic> dataList = jsonBody['data'] ?? [];
return dataList.map((json) => VendorBookingModel.fromJson(json)).toList();
} else {
throw Exception('Failed to fetch booking details');
}
}
}
class ChangebookingstatusRepository {
Future<bool> changebooking({
required String url,
required String id,
required String status,
}) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('vendor_id') ?? '';
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'id': id, 'user_id': userId, 'status': status}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
return jsonBody['success'] == true ||
jsonBody['status'] == 'success' ||
jsonBody['message']?.toLowerCase().contains('success') == true;
} else {
throw Exception('Failed to update booking status');
}
}
}
class VendorcatgoriesRepository {
Future<List<VendorCategoriesModel>> fetchvendorcat(String url) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('vendor_id') ?? '';
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'vendor_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> dataList = jsonBody['data'] ?? [];
return dataList
.map((json) => VendorCategoriesModel.fromJson(json))
.toList();
} else {
throw Exception('Failed to fetch booking details');
}
}
}
class VendorserviceRepository {
Future<List<VendorServiceModel>> fetchvendorservice(String url) async {
try {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('vendor_id') ?? '';
if (userId.isEmpty) {
throw Exception('Vendor ID not found in SharedPreferences');
}
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'vendor_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
// Add more detailed logging
if (jsonBody['data'] == null) {
return [];
}
final List<dynamic> dataList = jsonBody['data'] ?? [];
return dataList
.map((json) => VendorServiceModel.fromJson(json))
.toList();
} else {
throw Exception(
'Failed to fetch service details: ${response.statusCode}',
);
}
} catch (e) {
throw Exception('Failed to fetch service details: $e');
}
}
}
// Updated API Service Class
class Vendorserviceupadate {
Future<Map<String, dynamic>> vendorserviceupdate(
String url,
VendorServiceUploadModel serviceupload,
List<File> newImages,
) async {
try {
var request = http.MultipartRequest('POST', Uri.parse(url));
// Add all basic fields
request.fields.addAll({
'id': serviceupload.id,
'vendorname': serviceupload.vendorName,
'servicename': serviceupload.serviceName,
'service_type': serviceupload.serviceType,
'category': serviceupload.category,
'subcategory': serviceupload.subcategory,
'workinghours': serviceupload.workingHours,
'workingduration': serviceupload.workingDuration,
'amount': serviceupload.amount.toString(),
'location': serviceupload.location,
'description': serviceupload.description ?? '',
'details': serviceupload.details,
});
// Handle videos - send as JSON string
if (serviceupload.videos.isNotEmpty) {
request.fields['videos'] = jsonEncode(serviceupload.videos);
print('Videos JSON: ${request.fields['videos']}');
}
// Process ALL images (existing + new) as multipart files
List<File> allImageFiles = [];
// Step 1: Convert existing images (URLs) to files if needed
if (serviceupload.images.isNotEmpty) {
print('Processing ${serviceupload.images.length} existing images...');
for (int i = 0; i < serviceupload.images.length; i++) {
final imageUrl = serviceupload.images[i];
print('Processing existing image $i: $imageUrl');
try {
// If it's already a local file path
if (imageUrl.startsWith('/') || imageUrl.startsWith('file://')) {
final file = File(imageUrl.replaceFirst('file://', ''));
if (await file.exists()) {
allImageFiles.add(file);
} else {
print('⚠ Existing file not found: ${file.path}');
}
}
// If it's a URL, download it
else if (imageUrl.startsWith('http')) {
final downloadedFile = await _downloadImageAsFile(imageUrl, i);
if (downloadedFile != null) {
allImageFiles.add(downloadedFile);
print(
'✓ Downloaded and added existing image: ${downloadedFile.path}',
);
} else {
print('⚠ Failed to download existing image: $imageUrl');
}
}
// If it's a relative path or asset
else {
print('⚠ Unsupported existing image format: $imageUrl');
}
} catch (e) {
print('⚠ Error processing existing image $imageUrl: $e');
}
}
}
// Step 2: Add new images to the list
allImageFiles.addAll(newImages);
print('Total images to upload: ${allImageFiles.length}');
// Step 3: Upload all images with same field name 'images[]'
if (allImageFiles.isNotEmpty) {
print('Processing ${allImageFiles.length} total images for upload...');
for (int i = 0; i < allImageFiles.length; i++) {
final file = allImageFiles[i];
// Validate file exists
if (!await file.exists()) {
print('WARNING: File does not exist: ${file.path}');
continue;
}
// Get file info
final fileSize = await file.length();
final fileName = file.path.split('/').last;
final extension = fileName.split('.').last.toLowerCase();
print('Processing file $i: $fileName ($fileSize bytes)');
// Validate file size (5MB limit)
if (fileSize > 5 * 1024 * 1024) {
continue;
}
// Determine MIME type
String mimeType;
switch (extension) {
case 'png':
mimeType = 'image/png';
break;
case 'jpg':
case 'jpeg':
mimeType = 'image/jpeg';
break;
case 'gif':
mimeType = 'image/gif';
break;
case 'webp':
mimeType = 'image/webp';
break;
default:
mimeType = 'image/jpeg';
}
// Create unique filename for upload
final uploadFileName =
'upload_${DateTime.now().millisecondsSinceEpoch}_$i.$extension';
try {
// Method 1: Try fromPath (preferred)
var multipartFile = await http.MultipartFile.fromPath(
'images[]', // All images use same field name
file.path,
filename: uploadFileName,
contentType: MediaType.parse(mimeType),
);
request.files.add(multipartFile);
} catch (fromPathError) {
// Method 2: Fallback to fromBytes
try {
final bytes = await file.readAsBytes();
var multipartFile = http.MultipartFile.fromBytes(
'images[]',
bytes,
filename: uploadFileName,
contentType: MediaType.parse(mimeType),
);
request.files.add(multipartFile);
// ignore: empty_catches
} catch (fromBytesError) {}
}
}
} else {
print('No images to upload');
}
// Add headers
request.headers.addAll({
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
});
// Debug request info
print('=== REQUEST SUMMARY ===');
print('Fields: ${request.fields.keys.toList()}');
print('Files: ${request.files.length}');
for (var file in request.files) {
print(
' - Field: ${file.field}, Filename: ${file.filename}, Length: ${file.length}',
);
}
// Send request with timeout
print('Sending request...');
var streamedResponse = await request.send().timeout(
Duration(seconds: 120), // 2 minute timeout for large uploads
onTimeout: () {
throw TimeoutException('Upload timeout after 2 minutes');
},
);
var response = await http.Response.fromStream(streamedResponse);
print('=== RESPONSE INFO ===');
print('Status Code: ${response.statusCode}');
print('Response Headers: ${response.headers}');
print('Response Body Length: ${response.body.length}');
print(
'Response Body Preview: ${response.body.length > 500 ? "${response.body.substring(0, 500)}..." : response.body}',
);
// Handle response
if (response.statusCode >= 200 && response.statusCode < 300) {
try {
final decoded = jsonDecode(response.body) as Map<String, dynamic>;
print('✓ Successfully parsed JSON response');
return decoded;
} catch (jsonError) {
print('⚠ JSON parsing failed: $jsonError');
// Return success with raw response if JSON parsing fails but status is OK
return {
'success': true,
'message': 'Update completed successfully',
'raw_response': response.body,
};
}
} else {
// Handle error response
String errorMessage;
try {
final errorResponse = jsonDecode(response.body);
errorMessage =
errorResponse['message'] ??
errorResponse['error'] ??
'Server returned status ${response.statusCode}';
} catch (e) {
errorMessage =
'Server error (${response.statusCode}): ${response.body}';
}
print('✗ Server error: $errorMessage');
throw Exception(errorMessage);
}
} on TimeoutException catch (e) {
print('✗ Timeout error: $e');
throw Exception(
'Upload timeout. Please check your connection and try again.',
);
} on SocketException catch (e) {
print('✗ Network error: $e');
throw Exception('Network error. Please check your internet connection.');
} on http.ClientException catch (e) {
print('✗ HTTP client error: $e');
throw Exception('Connection error: ${e.message}');
} catch (e) {
print('✗ Unexpected error: $e');
rethrow;
}
}
// Helper method to download existing images from URLs
Future<File?> _downloadImageAsFile(String imageUrl, int index) async {
try {
final response = await http.get(Uri.parse(imageUrl));
if (response.statusCode == 200) {
// Get app's temporary directory
final directory = await getTemporaryDirectory();
// Determine file extension from URL or content type
String extension = 'jpg';
if (imageUrl.contains('.png')) {
extension = 'png';
} else if (imageUrl.contains('.gif'))
extension = 'gif';
else if (imageUrl.contains('.webp'))
extension = 'webp';
else if (response.headers['content-type']?.contains('png') == true)
extension = 'png';
// Create temporary file
final fileName =
'existing_image_${index}_${DateTime.now().millisecondsSinceEpoch}.$extension';
final file = File('${directory.path}/$fileName');
// Write downloaded bytes to file
await file.writeAsBytes(response.bodyBytes);
return file;
} else {
print('Failed to download image: ${response.statusCode}');
return null;
}
} catch (e) {
print('Error downloading image $imageUrl: $e');
return null;
}
}
}
// Image Upload Helper Class
class ImageUploadHelper {
static Future<List<File>> pickMultipleImages() async {
try {
final picker = ImagePicker();
final List<XFile> pickedFiles = await picker.pickMultiImage(
maxWidth: 1920,
maxHeight: 1920,
imageQuality: 85,
);
List<File> validFiles = [];
for (XFile xFile in pickedFiles) {
File file = File(xFile.path);
if (await validateImageFile(file)) {
validFiles.add(file);
} else {
print('Invalid image file: ${xFile.name}');
}
}
return validFiles;
} catch (e) {
print('Error picking images: $e');
return [];
}
}
static Future<bool> validateImageFile(File file) async {
try {
if (!await file.exists()) {
print('File does not exist: ${file.path}');
return false;
}
// Check file size (max 5MB)
int fileSize = await file.length();
if (fileSize > 5 * 1024 * 1024) {
print('File too large: ${file.path} ($fileSize bytes)');
return false;
}
// Check file extension
String extension = file.path.split('.').last.toLowerCase();
List<String> validExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
if (!validExtensions.contains(extension)) {
print('Invalid file extension: $extension');
return false;
}
return true;
} catch (e) {
print('Error validating file: $e');
return false;
}
}
}
class VendorExpiredPlanRepository {
Future<ExpiredPlanModel> fetchvendorExpiredPlan(String url) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('vendor_id') ?? '';
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'user_id': userId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final Map<String, dynamic> data = jsonBody['data'] ?? {};
return ExpiredPlanModel.fromJson(data);
} else {
throw Exception('Failed to fetch expired plan');
}
}
}
class DetailpageRepository {
Future<List<DetailPageModel>> fetchDetailpage(
String url,
int serviceid,
) async {
final response = await http.get(
Uri.parse('$url?service_id=$serviceid'),
headers: {'Content-Type': 'application/json'},
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final data = jsonBody['data'];
// Handle single object or list
if (data is List) {
return data.map((e) => DetailPageModel.fromJson(e)).toList();
} else if (data is Map<String, dynamic>) {
return [DetailPageModel.fromJson(data)];
} else {
return [];
}
} else {
throw Exception('Failed to load detail page');
}
}
}
class CatManagementDeleteRepository {
Future<bool> deleteCategoryManagement(String url, String categoryId) async {
final prefs = await SharedPreferences.getInstance();
final vendorId = prefs.getString('vendor_id') ?? '';
try {
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'vendor_id': vendorId, 'category': categoryId}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
return jsonBody['success'] == true ||
jsonBody['status'] == 'success' ||
jsonBody['message']?.toLowerCase().contains('success') == true;
} else {
throw Exception('Failed to delete category: ${response.statusCode}');
}
} catch (e) {
throw Exception('Network error: $e');
}
}
}
class SerciceDeleteRepository {
Future<bool> deleteService(String url, String id) async {
final prefs = await SharedPreferences.getInstance();
final vendorId = prefs.getString('vendor_id') ?? '';
try {
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'vendor_id': vendorId, 'id': id}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
return jsonBody['success'] == true ||
jsonBody['status'] == 'success' ||
jsonBody['message']?.toLowerCase().contains('success') == true;
} else {
throw Exception('Failed to delete service: ${response.statusCode}');
}
} catch (e) {
throw Exception('Network error: $e');
}
}
}
class ProfilegetvendorRepository {
Future<List<ProfileGetModel>> fetchprofilegetvendor(String url) async {
// Retrieve userId from SharedPreferences
final prefs = await SharedPreferences.getInstance();
final vendorid = prefs.getString('vendor_id') ?? '';
// Debugging: Print the userId to make sure it's correct
print('vendor_id: $vendorid');
// Check if userId is available before making the request
if (vendorid.isEmpty) {
throw Exception('User ID is not available.');
}
// Send the userId in the API request
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'vendor_id': vendorid}),
);
// Check if the response status code is successful
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> list = jsonBody['data'] ?? [];
// Convert the JSON response to a list of ProfileGetModel objects
return list.map((e) => ProfileGetModel.fromJson(e)).toList();
} else {
// Handle API errors
throw Exception(
'Failed to load profile data, status code: ${response.statusCode}',
);
}
}
}
class ProfileupdatevendorRepository {
Future<List<VendorProfileModel>> fetchProfileupdatevendor(String url) async {
final prefs = await SharedPreferences.getInstance();
final vendorid = prefs.getString('vendor_id') ?? '';
if (vendorid.isEmpty) throw Exception('User ID is not available.');
final response = await http.post(
Uri.parse(url),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'vendor_id': vendorid}),
);
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
final List<dynamic> list = jsonBody['data'] ?? [];
return list.map((e) => VendorProfileModel.fromJson(e)).toList();
} else {
throw Exception('Failed to load profile, code: ${response.statusCode}');
}
}
Future<void> updateProfilevendor({
required String url,
required String name,
required String number,
required String email,
required String address,
File? imageFile,
}) async {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('vendor_id') ?? '';
final request = http.MultipartRequest('POST', Uri.parse(url));
request.fields['vendor_id'] = userId;
request.fields['name'] = name;
request.fields['number'] = number;
request.fields['email'] = email;
request.fields['address'] = address;
if (imageFile != null) {
request.files.add(
await http.MultipartFile.fromPath(
'profile_pic', // Make sure this matches your backend key
imageFile.path,
contentType: MediaType('image', 'jpeg'), // Optional but recommended
),
);
}
final response = await request.send();
if (response.statusCode != 200) {
throw Exception('Failed to update profile');
}
}
}
class TermsAndConditionsRepository {
Future<TermsAndConditionsModel> fetchTermsAndCondition(String url) async {
try {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
return TermsAndConditionsModel.fromJson(jsonBody);
} else {
throw Exception(
'Failed to load terms and conditions, status code: ${response.statusCode}',
);
}
} catch (e) {
throw Exception('Failed to fetch terms and conditions: $e');
}
}
}
class PrivacypolicyRepository {
Future<TermsAndConditionsModel> fetchPrivacypolicy(String url) async {
try {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
return TermsAndConditionsModel.fromJson(jsonBody);
} else {
throw Exception(
'Failed to load terms and conditions, status code: ${response.statusCode}',
);
}
} catch (e) {
throw Exception('Failed to fetch terms and conditions: $e');
}
}
}
class NotificationRepository {
Future<List<NotificationModel>> fetchNotification({
required int type,
required String userId,
}) async {
try {
final uri = Uri.parse(ConstsApi.notification);
final response = await http.post(
uri,
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'type': type, 'user_id': userId}),
);
print('Fetching notification from: $uri');
print('Status Code: ${response.statusCode}');
print('Response Body: ${response.body}');
if (response.statusCode == 200) {
final jsonBody = jsonDecode(response.body);
// Handle if data is inside "data" key
if (jsonBody is Map && jsonBody['data'] is List) {
final List dataList = jsonBody['data'];
return dataList
.map<NotificationModel>((e) => NotificationModel.fromJson(e))
.toList();
}
// Handle if directly a List
if (jsonBody is List) {
return jsonBody
.map<NotificationModel>((e) => NotificationModel.fromJson(e))
.toList();
}
return []; // no recognizable data
} else {
throw Exception('Status Code: ${response.statusCode}');
}
} catch (e) {
print('Error fetching notification: $e');
throw Exception('Failed to fetch notification: $e');
}
}
}