onufitness_mobile/lib/services/api_services/base_api_services.dart
2026-01-13 11:36:24 +05:30

651 lines
20 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:onufitness/constants/api_endpoints.dart';
import 'package:image_picker/image_picker.dart';
import 'package:file_picker/file_picker.dart';
import 'package:onufitness/controller/update_acces_token_controller.dart';
import 'package:onufitness/routes/route_constant.dart';
import 'package:onufitness/services/local_storage_services/shared_services.dart';
import 'package:http_parser/http_parser.dart';
import 'package:mime/mime.dart';
import 'package:onufitness/services/notification_services/notification_service.dart';
class ApiBase {
static void handleAccountDeleted() {
Get.defaultDialog(
title: "Account Deactivated",
middleText:
"Your account has been deactivated by the administrator. You will now be logged out.",
textConfirm: "OK",
confirmTextColor: Colors.white,
barrierDismissible: false,
onConfirm: () async {
await SharedServices.logout();
await NotificationService().deleteDeviceToken();
Get.offNamedUntil(RouteConstant.loginFirstScreen, (route) => false);
},
);
}
//.............................................................................
static url({required String extendedURL}) {
log("${ApiUrl.baseUrl}$extendedURL");
return Uri.parse("${ApiUrl.baseUrl}$extendedURL");
}
//.............................................................................
static Future<http.Response> getRequest({
required String extendedURL,
String? token,
bool sendHeaders = true,
}) async {
var client = http.Client();
Map<String, String> newHeaders = {};
Map<String, String> contentType = {'Content-Type': 'application/json'};
newHeaders.addAll(contentType);
// Add the Authorization header if needed
if (sendHeaders && SharedServices.isLoggedIn()) {
newHeaders.addAll({'Authorization': token ?? SharedServices.userAuth()});
}
log("URL : ${ApiUrl.baseUrl}$extendedURL");
http.Response response = await client.get(
url(extendedURL: extendedURL.trim()),
headers: sendHeaders ? newHeaders : null,
);
// It Token Expired, then api call for update the token.....................
if (response.statusCode == 401) {
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
if (isSuccess) {
return getRequest(
extendedURL: extendedURL,
sendHeaders: sendHeaders,
token: token,
);
}
}
// ✅Handle account deleted (403)
if (response.statusCode == 403) {
handleAccountDeleted();
}
return response;
}
//.............................................................................
static Future<http.Response> postRequest({
required String extendedURL,
required Object body,
String? token,
bool sendHeaders = true,
}) async {
var client = http.Client();
Map<String, String> newHeaders = {};
Map<String, String> contentType = {'Content-Type': 'application/json'};
newHeaders.addAll(contentType);
// Add the Authorization header if needed
if (sendHeaders && SharedServices.isLoggedIn()) {
newHeaders.addAll({'Authorization': token ?? SharedServices.userAuth()});
}
log("URL : ${ApiUrl.baseUrl}$extendedURL");
http.Response response = await client.post(
url(extendedURL: extendedURL),
headers: newHeaders, // Always send headers for POST requests
body: jsonEncode(body),
);
// It Token Expired, then api call for update the token.....................
// 401 is the status code of UnAuthorize user................................
if (response.statusCode == 401) {
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
if (isSuccess) {
return postRequest(
extendedURL: extendedURL,
body: body,
sendHeaders: sendHeaders,
token: token,
);
}
}
// ✅Handle account deleted (403)
if (response.statusCode == 403) {
handleAccountDeleted();
}
return response;
}
//.............................................................................
static Future<http.Response> putRequest({
required String extendedURL,
required Object body,
String? token,
bool sendHeaders = true,
}) async {
var client = http.Client();
Map<String, String> newHeaders = {};
Map<String, String> contentType = {'Content-Type': 'application/json'};
newHeaders.addAll(contentType);
// Add the Authorization header if needed
if (sendHeaders && SharedServices.isLoggedIn()) {
newHeaders.addAll({'Authorization': token ?? SharedServices.userAuth()});
}
log("URL : ${ApiUrl.baseUrl}$extendedURL");
http.Response response = await client.put(
url(extendedURL: extendedURL),
headers: newHeaders, // Always send headers for PUT requests
body: jsonEncode(body),
);
// It Token Expired, then api call for update the token.....................
// 401 is the status code of UnAuthorize user................................
if (response.statusCode == 401) {
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
if (isSuccess) {
return putRequest(
extendedURL: extendedURL,
body: body,
sendHeaders: sendHeaders,
token: token,
);
}
}
// ✅Handle account deleted (403)
if (response.statusCode == 403) {
handleAccountDeleted();
}
return response;
}
//.............................................................................
static Future<http.Response> patchRequest({
required String extendedURL,
Object? body,
String? token,
bool sendHeaders = true,
}) async {
var client = http.Client();
Map<String, String> newHeaders = {};
Map<String, String> contentType = {'Content-Type': 'application/json'};
newHeaders.addAll(contentType);
// Add the Authorization header if needed
if (sendHeaders && SharedServices.isLoggedIn()) {
newHeaders.addAll({'Authorization': token ?? SharedServices.userAuth()});
}
log("URL : ${ApiUrl.baseUrl}$extendedURL");
http.Response response = await client.patch(
url(extendedURL: extendedURL),
headers: newHeaders, // Always send headers for Patch requests
body: jsonEncode(body),
);
// It Token Expired, then api call for update the token.....................
// 401 is the status code of UnAuthorize user................................
if (response.statusCode == 401) {
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
if (isSuccess) {
return patchRequest(
extendedURL: extendedURL,
body: body,
sendHeaders: sendHeaders,
token: token,
);
}
}
// ✅Handle account deleted (403)
if (response.statusCode == 403) {
handleAccountDeleted();
}
return response;
}
//.............................................................................
static Future<http.Response> deleteRequest({
required String extendedURL,
required Object body,
String? token,
bool sendHeaders = true,
}) async {
var client = http.Client();
Map<String, String> newHeaders = {};
Map<String, String> contentType = {'Content-Type': 'application/json'};
newHeaders.addAll(contentType);
// Add the Authorization header if needed
if (sendHeaders && SharedServices.isLoggedIn()) {
newHeaders.addAll({'Authorization': token ?? SharedServices.userAuth()});
}
log("URL : ${ApiUrl.baseUrl}$extendedURL");
http.Response response = await client.delete(
url(extendedURL: extendedURL),
headers: newHeaders, // Always send headers for Delete requests
body: jsonEncode(body),
);
// It Token Expired, then api call for update the token.....................
// 401 is the status code of UnAuthorize user................................
if (response.statusCode == 401) {
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
if (isSuccess) {
return deleteRequest(
extendedURL: extendedURL,
body: body,
sendHeaders: sendHeaders,
token: token,
);
}
}
// ✅Handle account deleted (403)
if (response.statusCode == 403) {
handleAccountDeleted();
}
return response;
}
//.............................................................................
static Future<http.Response> postSingleFileRequest({
required String extendedURL,
required XFile file,
Map<String, dynamic>? body,
String? token,
bool sendHeaders = true,
required String fileNameKey,
}) async {
try {
final uri = url(extendedURL: extendedURL);
var request = http.MultipartRequest('POST', uri);
Map<String, String> newHeaders = {};
if (sendHeaders && SharedServices.isLoggedIn()) {
newHeaders['Authorization'] = token ?? SharedServices.userAuth();
}
request.headers.addAll(newHeaders);
if (body != null) {
request.fields.addAll(
body.map((key, value) => MapEntry(key, value.toString())),
);
}
request.files.add(
await http.MultipartFile.fromPath(fileNameKey, file.path),
);
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
log('Upload response status: ${response.statusCode}');
log('Upload response body: ${response.body}');
if (response.statusCode == 401) {
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
if (isSuccess) {
return postSingleFileRequest(
extendedURL: extendedURL,
body: body,
sendHeaders: sendHeaders,
token: token,
file: file,
fileNameKey: fileNameKey,
);
}
}
// ✅Handle account deleted (403)
if (response.statusCode == 403) {
handleAccountDeleted();
}
return response;
} catch (e, stackTrace) {
log("Error uploading image: $e");
log("StackTrace: $stackTrace");
return http.Response('Error uploading image', 500);
}
}
//.............................................................................
static Future<http.Response> postMultipleFiles({
required String extendedURL,
required List<XFile> files,
Map<String, dynamic>? body,
required String fileNameKey,
String? token,
bool sendHeaders = true,
}) async {
try {
var request = http.MultipartRequest(
'POST',
url(extendedURL: extendedURL),
);
Map<String, String> newHeaders = {};
if (sendHeaders && SharedServices.isLoggedIn()) {
newHeaders['Authorization'] = token ?? SharedServices.userAuth();
}
request.headers.addAll(newHeaders);
// Add body fields if any
if (body != null) {
request.fields.addAll(
body.map((key, value) => MapEntry(key, value.toString())),
);
}
// 🔽 Add each file with proper MIME type
for (var file in files) {
final mimeType =
lookupMimeType(file.path) ?? 'application/octet-stream';
final mimeSplit = mimeType.split('/');
request.files.add(
await http.MultipartFile.fromPath(
fileNameKey,
file.path,
contentType: MediaType(mimeSplit[0], mimeSplit[1]),
filename: file.name,
),
);
log("Added file: ${file.name}, MimeType: $mimeType");
}
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
if (response.statusCode == 401) {
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
if (isSuccess) {
return postMultipleFiles(
extendedURL: extendedURL,
body: body,
sendHeaders: sendHeaders,
token: token,
files: files,
fileNameKey: fileNameKey,
);
}
}
// ✅Handle account deleted (403)
if (response.statusCode == 403) {
handleAccountDeleted();
}
return response;
} catch (e, stackTrace) {
log("Error uploading files: $e");
log("StackTrace: $stackTrace");
return http.Response('Error uploading files', 500);
}
}
//.........post Video Image and Documents with Mime Type..........................................................................................................
static Future<http.Response> postAnyFileWithMimeType({
required String extendedURL,
XFile? file, // Made file optional
Map<String, dynamic>? body,
String? token,
bool sendHeaders = true,
String? fileNameKey, // Made fileNameKey optional since file is optional
}) async {
try {
final uri = url(extendedURL: extendedURL);
var request = http.MultipartRequest('POST', uri);
Map<String, String> newHeaders = {};
if (sendHeaders && SharedServices.isLoggedIn()) {
newHeaders['Authorization'] = token ?? SharedServices.userAuth();
}
request.headers.addAll(newHeaders);
if (body != null) {
request.fields.addAll(
body.map((key, value) => MapEntry(key, value.toString())),
);
}
// ✅ Only add file if it's provided...........................................
if (file != null && fileNameKey != null) {
final mimeType =
lookupMimeType(file.path) ?? 'application/octet-stream';
final mimeSplit = mimeType.split('/');
request.files.add(
await http.MultipartFile.fromPath(
fileNameKey,
file.path,
contentType: MediaType(mimeSplit[0], mimeSplit[1]),
filename: file.name,
),
);
log("File Name : ${file.name}");
log("Mime Type : $mimeType");
}
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
log('Upload response status: ${response.statusCode}');
log('Upload response body: ${response.body}');
if (response.statusCode == 401) {
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
if (isSuccess) {
return await postAnyFileWithMimeType(
extendedURL: extendedURL,
body: body,
sendHeaders: sendHeaders,
token: token,
file: file,
fileNameKey: fileNameKey,
);
}
}
// ✅Handle account deleted (403)
if (response.statusCode == 403) {
handleAccountDeleted();
}
return response;
} catch (e, stackTrace) {
log("Error uploading: $e");
log("StackTrace: $stackTrace");
return http.Response('Error uploading', 500);
}
}
//............................................................................
// NEW METHOD: Post with multiple files having different field names
//............................................................................
static Future<http.Response> postMultipleIndivisualFiles({
required String extendedURL,
Map<String, dynamic>? body,
Map<String, dynamic>?
files, // Map of fieldName -> file (PlatformFile or XFile)
String? token,
bool sendHeaders = true,
}) async {
try {
var request = http.MultipartRequest(
'POST',
url(extendedURL: extendedURL),
);
Map<String, String> newHeaders = {};
if (sendHeaders && SharedServices.isLoggedIn()) {
newHeaders['Authorization'] = token ?? SharedServices.userAuth();
}
request.headers.addAll(newHeaders);
// Add body fields if any
if (body != null) {
request.fields.addAll(
body.map((key, value) => MapEntry(key, value.toString())),
);
}
// Add files with different field names
if (files != null) {
for (var entry in files.entries) {
final fieldName = entry.key;
final file = entry.value;
if (file != null) {
String filePath;
String fileName;
// Handle both PlatformFile and XFile
if (file is PlatformFile) {
filePath = file.path!;
fileName = file.name;
} else if (file is XFile) {
filePath = file.path;
fileName = file.name;
} else {
log("Unsupported file type for field: $fieldName");
continue;
}
final mimeType =
lookupMimeType(filePath) ?? 'application/octet-stream';
final mimeSplit = mimeType.split('/');
request.files.add(
await http.MultipartFile.fromPath(
fieldName,
filePath,
contentType: MediaType(mimeSplit[0], mimeSplit[1]),
filename: fileName,
),
);
log(
"Added file: $fileName to field: $fieldName, MimeType: $mimeType",
);
}
}
}
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
log('Upload response status: ${response.statusCode}');
log('Upload response body: ${response.body}');
if (response.statusCode == 401) {
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
if (isSuccess) {
return postMultipleIndivisualFiles(
extendedURL: extendedURL,
body: body,
files: files,
sendHeaders: sendHeaders,
token: token,
);
}
}
// ✅Handle account deleted (403)
if (response.statusCode == 403) {
handleAccountDeleted();
}
return response;
} catch (e, stackTrace) {
log("Error uploading files: $e");
log("StackTrace: $stackTrace");
return http.Response('Error uploading files', 500);
}
}
// Update File Patch Request...............................................................................
static Future<http.Response> patchAnyFileWithMimeType({
required String extendedURL,
XFile? file, // Made file optional
Map<String, dynamic>? body,
String? token,
bool sendHeaders = true,
String? fileNameKey, // Made fileNameKey optional since file is optional
}) async {
try {
final uri = url(extendedURL: extendedURL);
var request = http.MultipartRequest('PATCH', uri);
Map<String, String> newHeaders = {};
if (sendHeaders && SharedServices.isLoggedIn()) {
newHeaders['Authorization'] = token ?? SharedServices.userAuth();
}
request.headers.addAll(newHeaders);
if (body != null) {
request.fields.addAll(
body.map((key, value) => MapEntry(key, value.toString())),
);
}
// ✅ Only add file if it's provided...........................................
if (file != null && fileNameKey != null) {
final mimeType =
lookupMimeType(file.path) ?? 'application/octet-stream';
final mimeSplit = mimeType.split('/');
request.files.add(
await http.MultipartFile.fromPath(
fileNameKey,
file.path,
contentType: MediaType(mimeSplit[0], mimeSplit[1]),
filename: file.name,
),
);
log("File Name : ${file.name}");
log("Mime Type : $mimeType");
}
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
if (response.statusCode == 401) {
var isSuccess = await UpdateAccesTokenController.updateAccessToken();
if (isSuccess) {
return await postAnyFileWithMimeType(
extendedURL: extendedURL,
body: body,
sendHeaders: sendHeaders,
token: token,
file: file,
fileNameKey: fileNameKey,
);
}
}
// ✅Handle account deleted (403)
if (response.statusCode == 403) {
handleAccountDeleted();
}
return response;
} catch (e, stackTrace) {
log("Error uploading: $e");
log("StackTrace: $stackTrace");
return http.Response('Error uploading', 500);
}
}
}