connect with backend
This commit is contained in:
@@ -4,25 +4,43 @@ import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../services/auth_service.dart';
|
||||
|
||||
class AuthProvider extends ChangeNotifier {
|
||||
final AuthService _service = AuthService();
|
||||
AuthService? _service;
|
||||
|
||||
bool _loading = false;
|
||||
bool get loading => _loading;
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
String? _token;
|
||||
Map<String, dynamic>? _user;
|
||||
|
||||
String? get token => _token;
|
||||
Map<String, dynamic>? get user => _user;
|
||||
|
||||
bool get isLoggedIn => _token != null && _token!.isNotEmpty;
|
||||
|
||||
// Inject context after provider initializes
|
||||
void initContext(BuildContext context) {
|
||||
_service = AuthService(context);
|
||||
}
|
||||
|
||||
AuthProvider() {
|
||||
_loadFromPrefs();
|
||||
}
|
||||
|
||||
// ---------------------- NEW FIX: SAFE INIT -----------------------
|
||||
Future<void> init() async {
|
||||
if (!initialized) {
|
||||
await _loadFromPrefs();
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------- LOAD FROM PREFS -----------------------
|
||||
Future<void> _loadFromPrefs() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
_token = prefs.getString('token');
|
||||
|
||||
final userJson = prefs.getString('user');
|
||||
if (userJson != null) {
|
||||
try {
|
||||
@@ -31,22 +49,33 @@ class AuthProvider extends ChangeNotifier {
|
||||
_user = null;
|
||||
}
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> login(String loginId, String password) async {
|
||||
// -------------------------- LOGIN -----------------------------
|
||||
Future<Map<String, dynamic>> login(
|
||||
BuildContext context, String loginId, String password) async {
|
||||
_service ??= AuthService(context);
|
||||
|
||||
_loading = true;
|
||||
notifyListeners();
|
||||
|
||||
final res = await _service.login(loginId, password);
|
||||
final res = await _service!.login(loginId, password);
|
||||
|
||||
_loading = false;
|
||||
|
||||
if (res['success'] == true) {
|
||||
final token = res['token']?.toString();
|
||||
final userMap = res['user'] is Map ? Map<String, dynamic>.from(res['user']) : null;
|
||||
final userMap =
|
||||
res['user'] is Map ? Map<String, dynamic>.from(res['user']) : null;
|
||||
|
||||
if (token != null && userMap != null) {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString("saved_login_id", loginId);
|
||||
await prefs.setString("saved_password", password);
|
||||
|
||||
await _saveSession(token, userMap);
|
||||
}
|
||||
}
|
||||
@@ -55,27 +84,64 @@ class AuthProvider extends ChangeNotifier {
|
||||
return res;
|
||||
}
|
||||
|
||||
Future<void> _saveSession(String token, Map<String, dynamic> userMap) async {
|
||||
// --------------------- SAVE SESSION ---------------------------
|
||||
Future<void> _saveSession(
|
||||
String token, Map<String, dynamic> userMap) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('token', token);
|
||||
await prefs.setString('user', jsonEncode(userMap));
|
||||
|
||||
_token = token;
|
||||
_user = userMap;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
// optional: call API logout if implemented
|
||||
if (_token != null) {
|
||||
try {
|
||||
await _service.logout(_token!);
|
||||
} catch (_) {}
|
||||
}
|
||||
// ----------------------- LOGOUT -------------------------------
|
||||
Future<void> logout(BuildContext context) async {
|
||||
_service ??= AuthService(context);
|
||||
|
||||
try {
|
||||
await _service!.logout();
|
||||
} catch (_) {}
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('token');
|
||||
await prefs.remove('user');
|
||||
|
||||
_token = null;
|
||||
_user = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// -------------------- AUTO LOGIN ------------------------------
|
||||
Future<bool> autoLoginFromSavedCredentials(BuildContext context) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final loginId = prefs.getString('saved_login_id');
|
||||
final password = prefs.getString('saved_password');
|
||||
|
||||
if (loginId == null || password == null) return false;
|
||||
|
||||
final res = await login(context, loginId, password);
|
||||
return res['success'] == true;
|
||||
}
|
||||
|
||||
// --------------------- REFRESH TOKEN --------------------------
|
||||
Future<bool> tryRefreshToken(BuildContext context) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final oldToken = prefs.getString('token');
|
||||
|
||||
if (oldToken == null) return false;
|
||||
|
||||
_service ??= AuthService(context);
|
||||
|
||||
final res = await _service!.refreshToken(oldToken);
|
||||
|
||||
if (res['success'] == true && res['token'] != null) {
|
||||
await prefs.setString('token', res['token']);
|
||||
_token = res['token'];
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
39
lib/providers/dashboard_provider.dart
Normal file
39
lib/providers/dashboard_provider.dart
Normal file
@@ -0,0 +1,39 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../services/dashboard_service.dart';
|
||||
|
||||
class DashboardProvider extends ChangeNotifier {
|
||||
DashboardService? _service;
|
||||
|
||||
bool loading = false;
|
||||
|
||||
int activeOrders = 0;
|
||||
int inTransitOrders = 0;
|
||||
int deliveredOrders = 0;
|
||||
String totalValue = "0";
|
||||
double totalRaw = 0;
|
||||
|
||||
void init(BuildContext context) {
|
||||
_service = DashboardService(context);
|
||||
}
|
||||
|
||||
Future<void> loadSummary(BuildContext context) async {
|
||||
loading = true;
|
||||
notifyListeners();
|
||||
|
||||
_service ??= DashboardService(context);
|
||||
final res = await _service!.getSummary();
|
||||
|
||||
if (res['status'] == true) {
|
||||
final s = res['summary'];
|
||||
|
||||
activeOrders = s['active_orders'] ?? 0;
|
||||
inTransitOrders = s['in_transit_orders'] ?? 0;
|
||||
deliveredOrders = s['delivered_orders'] ?? 0;
|
||||
totalValue = s['total_value']?.toString() ?? "0";
|
||||
totalRaw = double.tryParse(s['total_raw'].toString()) ?? 0;
|
||||
}
|
||||
|
||||
loading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
73
lib/providers/invoice_installment_screen.dart
Normal file
73
lib/providers/invoice_installment_screen.dart
Normal file
@@ -0,0 +1,73 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../services/dio_client.dart';
|
||||
import '../services/invoice_service.dart';
|
||||
|
||||
class InvoiceInstallmentScreen extends StatefulWidget {
|
||||
final int invoiceId;
|
||||
const InvoiceInstallmentScreen({super.key, required this.invoiceId});
|
||||
|
||||
@override
|
||||
State<InvoiceInstallmentScreen> createState() =>
|
||||
_InvoiceInstallmentScreenState();
|
||||
}
|
||||
|
||||
class _InvoiceInstallmentScreenState extends State<InvoiceInstallmentScreen> {
|
||||
bool loading = true;
|
||||
List installments = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
load();
|
||||
}
|
||||
|
||||
Future<void> load() async {
|
||||
final service = InvoiceService(DioClient.getInstance(context));
|
||||
final res = await service.getInstallments(widget.invoiceId);
|
||||
|
||||
if (res['success'] == true) {
|
||||
installments = res['installments'] ?? [];
|
||||
}
|
||||
|
||||
loading = false;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text("Installments")),
|
||||
body: loading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: installments.isEmpty
|
||||
? const Center(
|
||||
child: Text("Installments not created yet",
|
||||
style: TextStyle(fontSize: 18)),
|
||||
)
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: installments.length,
|
||||
itemBuilder: (_, i) {
|
||||
final inst = installments[i];
|
||||
return Card(
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
"Amount: ₹${inst['amount']?.toString() ?? '0'}"),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Date: ${inst['installment_date'] ?? 'N/A'}"),
|
||||
Text(
|
||||
"Payment: ${inst['payment_method'] ?? 'N/A'}"),
|
||||
Text(
|
||||
"Reference: ${inst['reference_no'] ?? 'N/A'}"),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
23
lib/providers/invoice_provider.dart
Normal file
23
lib/providers/invoice_provider.dart
Normal file
@@ -0,0 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../services/invoice_service.dart';
|
||||
import '../services/dio_client.dart';
|
||||
|
||||
class InvoiceProvider extends ChangeNotifier {
|
||||
bool loading = false;
|
||||
List invoices = [];
|
||||
|
||||
Future<void> loadInvoices(BuildContext context) async {
|
||||
loading = true;
|
||||
notifyListeners();
|
||||
|
||||
final service = InvoiceService(DioClient.getInstance(context));
|
||||
final res = await service.getAllInvoices();
|
||||
|
||||
if (res['success'] == true) {
|
||||
invoices = res['invoices'] ?? [];
|
||||
}
|
||||
|
||||
loading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
45
lib/providers/mark_list_provider.dart
Normal file
45
lib/providers/mark_list_provider.dart
Normal file
@@ -0,0 +1,45 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../services/mark_list_service.dart';
|
||||
|
||||
class MarkListProvider extends ChangeNotifier {
|
||||
MarkListService? _service;
|
||||
|
||||
List<dynamic> marks = [];
|
||||
bool loading = false;
|
||||
|
||||
void init(BuildContext context) {
|
||||
_service = MarkListService(context);
|
||||
}
|
||||
|
||||
Future<void> loadMarks(BuildContext context) async {
|
||||
loading = true;
|
||||
notifyListeners();
|
||||
|
||||
_service ??= MarkListService(context);
|
||||
|
||||
final res = await _service!.getMarks();
|
||||
|
||||
if (res['success'] == true) {
|
||||
marks = res['data'] ?? [];
|
||||
}
|
||||
|
||||
loading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> addMark(BuildContext context, String mark, String origin, String destination) async {
|
||||
_service ??= MarkListService(context);
|
||||
|
||||
final res = await _service!.addMark({
|
||||
"mark_no": mark,
|
||||
"origin": origin,
|
||||
"destination": destination
|
||||
});
|
||||
|
||||
if (res['success'] == true) {
|
||||
await loadMarks(context); // refresh list
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
26
lib/providers/order_provider.dart
Normal file
26
lib/providers/order_provider.dart
Normal file
@@ -0,0 +1,26 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
import '../services/order_service.dart';
|
||||
|
||||
class OrderProvider extends ChangeNotifier {
|
||||
final OrderService service;
|
||||
|
||||
OrderProvider(this.service);
|
||||
|
||||
bool loading = false;
|
||||
List orders = [];
|
||||
|
||||
Future<void> loadOrders() async {
|
||||
loading = true;
|
||||
notifyListeners();
|
||||
|
||||
final res = await service.getOrders();
|
||||
|
||||
if (res['success'] == true) {
|
||||
orders = res['orders'];
|
||||
}
|
||||
|
||||
loading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
70
lib/providers/user_profile_provider.dart
Normal file
70
lib/providers/user_profile_provider.dart
Normal file
@@ -0,0 +1,70 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../models/user_profile.dart';
|
||||
import '../services/user_profile_service.dart';
|
||||
|
||||
class UserProfileProvider extends ChangeNotifier {
|
||||
UserProfileService? _service;
|
||||
|
||||
UserProfile? profile;
|
||||
bool loading = false;
|
||||
|
||||
void init(BuildContext context) {
|
||||
_service = UserProfileService(context);
|
||||
}
|
||||
|
||||
Future<void> loadProfile(BuildContext context) async {
|
||||
_service ??= UserProfileService(context);
|
||||
|
||||
loading = true;
|
||||
notifyListeners();
|
||||
|
||||
final res = await _service!.getProfile();
|
||||
|
||||
if (res['success'] == true) {
|
||||
profile = UserProfile.fromJson(res['data']);
|
||||
}
|
||||
|
||||
loading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<bool> updateProfileImage(BuildContext context, File image) async {
|
||||
_service ??= UserProfileService(context);
|
||||
|
||||
loading = true;
|
||||
notifyListeners();
|
||||
|
||||
final res = await _service!.updateProfileImage(image);
|
||||
|
||||
if (res['success'] == true) {
|
||||
profile = UserProfile.fromJson(res['data']);
|
||||
loading = false;
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
|
||||
loading = false;
|
||||
notifyListeners();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// NEW: Send profile update request (admin approval required)
|
||||
Future<bool> sendProfileUpdateRequest(
|
||||
BuildContext context,
|
||||
Map<String, dynamic> data,
|
||||
) async {
|
||||
_service ??= UserProfileService(context);
|
||||
|
||||
loading = true;
|
||||
notifyListeners();
|
||||
|
||||
final res = await _service!.sendUpdateRequest(data);
|
||||
|
||||
loading = false;
|
||||
notifyListeners();
|
||||
|
||||
return res['success'] == true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user