connect with backend

This commit is contained in:
Abhishek Mali
2025-12-03 11:57:05 +05:30
parent c6b4c66c10
commit 3bf27cc29d
48 changed files with 2618 additions and 126 deletions

View File

@@ -1,16 +1,16 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import '../config/api_config.dart';
import 'dio_client.dart';
class AuthService {
final Dio _dio = Dio(BaseOptions(
baseUrl: ApiConfig.baseUrl,
connectTimeout: const Duration(seconds: 15),
receiveTimeout: const Duration(seconds: 15),
// You can add headers here if needed:
// headers: {'Accept': 'application/json'},
));
late final Dio _dio;
/// Calls /api/user/login with login_id and password
AuthService(BuildContext context) {
_dio = DioClient.getInstance(context);
}
/// Login API
Future<Map<String, dynamic>> login(String loginId, String password) async {
try {
final response = await _dio.post('/user/login', data: {
@@ -18,45 +18,44 @@ class AuthService {
'password': password,
});
// Ensure we return a Map<String, dynamic>
if (response.data is Map) {
return Map<String, dynamic>.from(response.data);
} else {
return {
'success': false,
'message': 'Invalid response from server',
};
}
return Map<String, dynamic>.from(response.data);
} on DioException catch (e) {
// Try to extract message from server response
dynamic respData = e.response?.data;
String message = 'Login failed';
if (respData is Map && respData['message'] != null) {
message = respData['message'].toString();
} else if (e.message != null) {
message = e.message!;
}
final data = e.response?.data;
return {
'success': false,
'message': message,
'message': data is Map && data['message'] != null
? data['message']
: e.message ?? 'Login failed'
};
} catch (e) {
return {
'success': false,
'message': e.toString(),
};
}
}
/// Optional: logout (if you have logout endpoint)
Future<Map<String, dynamic>> logout(String token) async {
try {
final Dio dio = Dio(BaseOptions(baseUrl: ApiConfig.baseUrl));
dio.options.headers['Authorization'] = 'Bearer $token';
final response = await dio.post('/user/logout');
return Map<String, dynamic>.from(response.data ?? {'success': true});
} catch (e) {
return {'success': false, 'message': e.toString()};
}
}
/// Logout API
Future<Map<String, dynamic>> logout() async {
try {
final response = await _dio.post('/user/logout');
return Map<String, dynamic>.from(response.data);
} catch (e) {
return {'success': false, 'message': e.toString()};
}
}
/// Refresh token
Future<Map<String, dynamic>> refreshToken(String oldToken) async {
try {
final response = await _dio.post(
'/user/refresh',
options: Options(headers: {
'Authorization': 'Bearer $oldToken',
}),
);
return Map<String, dynamic>.from(response.data);
} on DioException catch (e) {
final msg = e.response?.data?['message'] ?? 'Refresh failed';
return {'success': false, 'message': msg};
}
}
}

View File

@@ -0,0 +1,20 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'dio_client.dart';
class DashboardService {
late final Dio _dio;
DashboardService(BuildContext context) {
_dio = DioClient.getInstance(context);
}
Future<Map<String, dynamic>> getSummary() async {
try {
final res = await _dio.get('/user/order-summary');
return Map<String, dynamic>.from(res.data);
} catch (e) {
return {'status': false, 'message': e.toString()};
}
}
}

View File

@@ -0,0 +1,33 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../config/api_config.dart';
import '../providers/auth_provider.dart';
import 'token_interceptor.dart';
class DioClient {
static Dio? _dio; // Singleton instance
static Dio getInstance(BuildContext context) {
if (_dio == null) {
_dio = Dio(
BaseOptions(
baseUrl: ApiConfig.baseUrl,
connectTimeout: const Duration(seconds: 15),
receiveTimeout: const Duration(seconds: 15),
headers: {
"Accept": "application/json",
},
),
);
final authProvider = Provider.of<AuthProvider>(context, listen: false);
_dio!.interceptors.add(
TokenInterceptor(authProvider, context, _dio!),
);
}
return _dio!;
}
}

View File

@@ -0,0 +1,34 @@
import 'package:dio/dio.dart';
class InvoiceService {
final Dio dio;
InvoiceService(this.dio);
Future<Map<String, dynamic>> getAllInvoices() async {
try {
final res = await dio.get("/user/invoices");
return Map<String, dynamic>.from(res.data);
} catch (e) {
return {"success": false, "message": e.toString()};
}
}
Future<Map<String, dynamic>> getInstallments(int invoiceId) async {
try {
final res = await dio.get("/user/invoice/$invoiceId/installments");
return Map<String, dynamic>.from(res.data);
} catch (e) {
return {"success": false, "message": e.toString()};
}
}
/// 🔵 NEW FUNCTION — Fetch Full Invoice Details
Future<Map<String, dynamic>> getInvoiceDetails(int invoiceId) async {
try {
final res = await dio.get("/user/invoice/$invoiceId/details");
return Map<String, dynamic>.from(res.data);
} catch (e) {
return {"success": false, "message": e.toString()};
}
}
}

View File

@@ -0,0 +1,29 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'dio_client.dart';
class MarkListService {
late Dio _dio;
MarkListService(BuildContext context) {
_dio = DioClient.getInstance(context);
}
Future<Map<String, dynamic>> addMark(Map<String, dynamic> data) async {
try {
final res = await _dio.post('/add-mark-no', data: data);
return Map<String, dynamic>.from(res.data);
} catch (e) {
return {'success': false, 'message': e.toString()};
}
}
Future<Map<String, dynamic>> getMarks() async {
try {
final res = await _dio.get('/show-mark-list');
return Map<String, dynamic>.from(res.data);
} catch (e) {
return {'success': false, 'message': e.toString()};
}
}
}

View File

@@ -0,0 +1,32 @@
import 'package:dio/dio.dart';
class OrderService {
final Dio _dio;
OrderService(this._dio);
Future<Map<String, dynamic>> getOrders() async {
final res = await _dio.get('/user/orders');
return res.data;
}
Future<Map<String, dynamic>> getOrderDetails(String id) async {
final res = await _dio.get('/user/order/$id/details');
return res.data;
}
Future<Map<String, dynamic>> getShipment(String id) async {
final res = await _dio.get('/user/order/$id/shipment');
return res.data;
}
Future<Map<String, dynamic>> getInvoice(String id) async {
final res = await _dio.get('/user/order/$id/invoice');
return res.data;
}
Future<Map<String, dynamic>> trackOrder(String id) async {
final res = await _dio.get('/user/order/$id/track');
return res.data;
}
}

View File

@@ -1,18 +1,19 @@
import 'package:dio/dio.dart';
import '../config/api_config.dart';
import 'package:flutter/material.dart';
import 'dio_client.dart';
class RequestService {
final Dio _dio = Dio(
BaseOptions(
baseUrl: ApiConfig.baseUrl,
connectTimeout: const Duration(seconds: 15),
),
);
/// Send signup request to backend (after OTP verified)
late final Dio _dio;
RequestService(BuildContext context) {
_dio = DioClient.getInstance(context);
}
/// Signup request after OTP
Future<Map<String, dynamic>> sendSignup(Map<String, dynamic> payload) async {
try {
final resp = await _dio.post('/signup-request', data: payload);
return resp.data is Map ? Map<String, dynamic>.from(resp.data) : {'status': true, 'message': 'OK'};
return Map<String, dynamic>.from(resp.data);
} on DioException catch (e) {
return {
'status': false,

View File

@@ -0,0 +1,37 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import '../providers/auth_provider.dart';
class TokenInterceptor extends Interceptor {
final AuthProvider auth;
final BuildContext context;
final Dio dio;
TokenInterceptor(this.auth, this.context, this.dio);
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
if (auth.token != null) {
options.headers['Authorization'] = 'Bearer ${auth.token}';
}
handler.next(options);
}
@override
void onError(DioException err, ErrorInterceptorHandler handler) async {
if (err.response?.statusCode == 401 &&
err.response?.data['message'] == 'Token has expired') {
final refreshed = await auth.tryRefreshToken(context);
if (refreshed) {
err.requestOptions.headers['Authorization'] = 'Bearer ${auth.token}';
final newResponse = await dio.fetch(err.requestOptions);
return handler.resolve(newResponse);
}
}
handler.next(err);
}
}

View File

@@ -0,0 +1,48 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'dio_client.dart';
class UserProfileService {
late final Dio _dio;
UserProfileService(BuildContext context) {
_dio = DioClient.getInstance(context);
}
/// Get profile
Future<Map<String, dynamic>> getProfile() async {
try {
final res = await _dio.get('/user/profile');
return Map<String, dynamic>.from(res.data);
} catch (e) {
return {"success": false, "message": e.toString()};
}
}
/// Update profile IMAGE only
Future<Map<String, dynamic>> updateProfileImage(File image) async {
try {
final form = FormData.fromMap({
"profile_image": await MultipartFile.fromFile(image.path),
});
final res = await _dio.post('/user/profile-image', data: form);
return Map<String, dynamic>.from(res.data);
} catch (e) {
return {"success": false, "message": e.toString()};
}
}
/// Send profile update request (admin approval needed)
Future<Map<String, dynamic>> sendUpdateRequest(Map<String, dynamic> data) async {
try {
final res = await _dio.post('/user/profile-update-request', data: data);
return Map<String, dynamic>.from(res.data);
} catch (e) {
return {"success": false, "message": e.toString()};
}
}
}